[gparted] Prevent core dump reading none UTF-8 data from external command (#777973)



commit a03735ac6f5e7e4d7282f7d0b06a97f337830858
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Fri Feb 17 18:45:27 2017 +0000

    Prevent core dump reading none UTF-8 data from external command (#777973)
    
    A user had a very corrupted FAT file system and when GParted was reading
    the file system usage it would core dump.  The tip of the stack trace
    was:
    
        #0 Glib::ustring_Iterator<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > >::operator++()
           at /usr/include/glibmm-2.4/glibmm/ustring.h line 957
        #1 Glib::ustring_Iterator<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, 
std::char_traits<char>, std::allocator<char> > > >::operator++(int)
           at /usr/include/glibmm-2.4/glibmm/ustring.h line 965
        #2 GParted::PipeCapture::OnReadable(Glib::IOCondition)
           at PipeCapture.cc line 63
        #3 GParted::PipeCapture::_OnReadable(_GIOChannel*, GIOCondition, void*)
           at PipeCapture.cc line 45
    
    GParted uses 'fsck.fat -n -v /dev/PTN' to get the file system usage.
    However because the file system was so corrupted it was reporting every
    file name as being damaged, including the file names being reported as
    binary data.  PipeCapture::OnReadable() reads up to 512 bytes at a time
    and then uses a Glib::ustring iterator to loop over the UTF-8
    characters, but a Glib::ustring iterator is explicitly not capable of
    reading binary data [1].  With invalid UTF-8 bytes the code continued to
    read beyond the end of the string until GParted crashed with a
    segmentation violation.
    
    Fix by accessing the read string by index instead of by iterator.
    
    [1] Quote from the Glib::ustring_Iterator<T> Class Template Reference:
        https://developer.gnome.org/glibmm/stable/classGlib_1_1ustring__Iterator.html
    
        "The Glib::ustring iterated over must contain only valid UTF-8 data.
        If it does not, operator++(), operator--() and operator*() may make
        accesses outside the bounds of the string."
    
    Bug 777973 - Segmentation fault on bad disk

 src/PipeCapture.cc |   18 +++++++++++-------
 1 files changed, 11 insertions(+), 7 deletions(-)
---
diff --git a/src/PipeCapture.cc b/src/PipeCapture.cc
index 2673f3b..5690f0f 100644
--- a/src/PipeCapture.cc
+++ b/src/PipeCapture.cc
@@ -15,7 +15,10 @@
  */
 
 #include "PipeCapture.h"
+
 #include <iostream>
+#include <glib.h>            // typedef gunichar
+#include <glibmm/ustring.h>
 
 namespace GParted {
 
@@ -60,31 +63,32 @@ bool PipeCapture::OnReadable( Glib::IOCondition condition )
        Glib::IOStatus status = channel->read( str, 512 );
        if (status == Glib::IO_STATUS_NORMAL)
        {
-               for( Glib::ustring::iterator s = str.begin(); s != str.end(); s++ )
+               for ( unsigned int i = 0 ; i < str.size() ; i ++ )
                {
-                       if( *s == '\b' ) {
+                       gunichar uc = str[i];
+                       if ( uc == '\b' ) {
                                if ( cursor > linestart )
                                        cursor -- ;
                        }
-                       else if( *s == '\r' )
+                       else if ( uc == '\r' )
                                cursor = linestart ;
-                       else if( *s == '\n' ) {
+                       else if ( uc == '\n' ) {
                                cursor = lineend ;
                                buff .append( 1, '\n' ) ;
                                cursor ++ ;
                                linestart = cursor ;
                                lineend = cursor ;
                        }
-                       else if (*s == '\x01' || *s == '\x02' )
+                       else if ( uc == '\x01' || uc == '\x02' )
                                //Skip Ctrl-A and Ctrl-B chars e2fsck uses to bracket the progress bar
                                continue;
                        else {
                                if ( cursor < lineend ) {
-                                       buff .replace( cursor, 1, 1, *s ) ;
+                                       buff.replace( cursor, 1, 1, uc );
                                        cursor ++ ;
                                }
                                else {
-                                       buff .append( 1, *s ) ;
+                                       buff.append( 1, uc );
                                        cursor ++ ;
                                        lineend = cursor ;
                                }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]