diff options
author | Dimitri van Heesch <dimitri@stack.nl> | 2015-01-02 08:56:45 (GMT) |
---|---|---|
committer | Dimitri van Heesch <dimitri@stack.nl> | 2015-01-02 09:45:18 (GMT) |
commit | 312bef563a5be72f6423377247db1b80044bf711 (patch) | |
tree | 3a656445fa67469b2f1783932fe127e9f39af69a /qtools | |
parent | ed39dab59f8af2c5b42cfac0b3140cf594412121 (diff) | |
download | Doxygen-312bef563a5be72f6423377247db1b80044bf711.zip Doxygen-312bef563a5be72f6423377247db1b80044bf711.tar.gz Doxygen-312bef563a5be72f6423377247db1b80044bf711.tar.bz2 |
Fixed a couple of cases where sharing string data could lead to corruption
Also made dangerous string access more visible by introducing rawData().
This replaces data() which will now return a constant string.
Diffstat (limited to 'qtools')
-rw-r--r-- | qtools/qcstring.cpp | 48 | ||||
-rw-r--r-- | qtools/qcstring.h | 50 | ||||
-rw-r--r-- | qtools/qtextcodec.cpp | 4 | ||||
-rw-r--r-- | qtools/qtextstream.cpp | 6 | ||||
-rw-r--r-- | qtools/qutfcodec.cpp | 6 |
5 files changed, 66 insertions, 48 deletions
diff --git a/qtools/qcstring.cpp b/qtools/qcstring.cpp index 49bf842..26df166 100644 --- a/qtools/qcstring.cpp +++ b/qtools/qcstring.cpp @@ -31,7 +31,7 @@ QCString &QCString::sprintf( const char *format, ... ) const int minlen=256; int l = length(); if (l<minlen) { resize(minlen); l=minlen; } - int n=vsnprintf( data(), l, format, ap); + int n=vsnprintf( rawData(), l, format, ap); if (n<0) n=l; resize(n+1); va_end( ap ); @@ -62,7 +62,7 @@ int QCString::find( const char *str, int index, bool cs ) const if (index<0 || index>=l) return -1; // index outside string if (!str) return -1; // no string to search for if (!*str) return index; // empty string matching at index - register char *pos; + register const char *pos; if (cs) // case sensitive { pos = strstr(data()+index,str); @@ -132,7 +132,7 @@ int QCString::findRev( const char *str, int index, bool cs) const else if (index>len) return -1; // bad index else if (index+slen>len) index=len-slen; // str would be too long if (index<0) return -1; // no match possible - register char *pos = data()+index; + register const char *pos = data()+index; if (cs) // case sensitive { for (int i=index; i>=0; i--) if (qstrncmp(pos--,str,slen)==0) return i; @@ -204,9 +204,7 @@ bool QCString::stripPrefix(const char *prefix) int len = qstrlen(prefix); if (qstrncmp(prefix,data(),len)==0) { - int newlen = length()-len+1; - qmemmove(data(),data()+len,newlen); - resize(newlen); + m_rep=mid(len,length()-len).m_rep; // need to make a deep copy return TRUE; } return FALSE; @@ -225,7 +223,7 @@ QCString QCString::left( uint len ) const else { QCString s( len+1 ); - memcpy( s.data(), data(), len); + memcpy( s.rawData(), data(), len); return s; } } @@ -255,9 +253,9 @@ QCString QCString::mid( uint index, uint len) const } else { - register char *p = data()+index; + register const char *p = data()+index; QCString s(len+1); - qstrncpy( s.data(), p, len+1 ); + qstrncpy( s.rawData(), p, len+1 ); return s; } } @@ -266,7 +264,7 @@ QCString QCString::lower() const { if (length()==0) return QCString(); QCString s(data()); - register char *pos = s.data(); + register char *pos = s.rawData(); if (pos) { while (*pos) @@ -282,7 +280,7 @@ QCString QCString::upper() const { if (length()==0) return QCString(); QCString s(data()); - register char *pos = s.data(); + register char *pos = s.rawData(); if (pos) { while (*pos) @@ -299,13 +297,13 @@ QCString QCString::stripWhiteSpace() const if ( isEmpty() ) // nothing to do return *this; - register char *s = data(); + register const char *cs = data(); int reslen = length(); - if ( !isspace((uchar)s[0]) && !isspace((uchar)s[reslen-1]) ) + if ( !isspace((uchar)cs[0]) && !isspace((uchar)cs[reslen-1]) ) return *this; // returns a copy - QCString result(s); - s = result.data(); + QCString result(cs); + register char *s = result.rawData(); int start = 0; int end = reslen - 1; while ( isspace((uchar) s[start]) ) // skip white space from start @@ -317,7 +315,7 @@ QCString QCString::stripWhiteSpace() const while ( end && isspace((uchar) s[end]) ) // skip white space from end end--; end -= start - 1; - qmemmove( result.data(), &s[start], end ); + qmemmove( s, &s[start], end ); result.resize( end + 1 ); return result; } @@ -328,8 +326,8 @@ QCString QCString::simplifyWhiteSpace() const return *this; QCString result( length()+1 ); - char *from = data(); - char *to = result.data(); + const char *from = data(); + char *to = result.rawData(); char *first = to; while ( TRUE ) { @@ -363,14 +361,14 @@ QCString &QCString::insert( uint index, const char *s ) if ((int)index>=olen) { resize(nlen+index-olen+1); - memset(data()+olen, ' ', index-olen); - memcpy(data()+index,s, len+1); + memset(rawData()+olen, ' ', index-olen); + memcpy(rawData()+index,s, len+1); } else { resize(nlen+1); - qmemmove(data()+index+len,data()+index,olen-index+1); - memcpy(data()+index,s,len); + qmemmove(rawData()+index+len,data()+index,olen-index+1); + memcpy(rawData()+index,s,len); } return *this; } @@ -402,8 +400,10 @@ QCString &QCString::remove( uint index, uint len ) } else if ( len != 0 ) { - qmemmove( data()+index, data()+index+len, olen-index-len+1 ); + QCString tmp(olen-index-len+1); + qmemmove( tmp.rawData(), data()+index+len, olen-index-len+1 ); resize( olen-len+1 ); + memcpy( rawData()+index,tmp.data(),tmp.length() ); } return *this; } @@ -635,7 +635,7 @@ QDataStream &operator>>( QDataStream &s, QCString &str ) len = 0; } if ( len > 0 ) // not null array - s.readRawBytes( str.data(), (uint)len ); + s.readRawBytes( str.rawData(), (uint)len ); return s; } diff --git a/qtools/qcstring.h b/qtools/qcstring.h index bc3a091..8854aa7 100644 --- a/qtools/qcstring.h +++ b/qtools/qcstring.h @@ -204,11 +204,20 @@ public: } /** Returns a pointer to the contents of the string in the form of a 0-terminated C string */ - char *data() const + const char *data() const { return m_rep.data(); } + /** Returns a writable pointer to the data. + * @warning if the string is shared it will modifying the string directly and + * this will overwrite all copies as well! + */ + char *rawData() const + { + return m_rep.rawData(); + } + /** Resizes the string to hold \a newlen characters * (this value should include the 0-terminator). If the string is enlarged the contents will * be left unmodified. @@ -242,7 +251,7 @@ public: { if (length()==0) return QCString(); QCString cs(length()+1); - memcpy(cs.data(),data(),length()); + memcpy(cs.rawData(),data(),length()); return cs; } @@ -299,7 +308,7 @@ public: int len1 = length(); int len2 = (int)strlen(str); resize(len1+len2+1); - memcpy(data()+len1,str,len2); + memcpy(rawData()+len1,str,len2); return *this; } @@ -308,7 +317,7 @@ public: { int len = length(); resize(len+2); - data()[len]=c; + rawData()[len]=c; return *this; } @@ -568,9 +577,21 @@ public: } uint length() const { - return u.s.isShort ? u.s.len : u.l.d->len; + uint l = u.s.isShort ? u.s.len : u.l.d->len; + return l; } - char *data() const + const char *data() const + { + if (u.s.isShort) + { + return u.s.len==0 ? 0 : u.s.str; + } + else + { + return u.l.d->len==0 ? 0 : u.l.d->toStr(); + } + } + char *rawData() const { if (u.s.isShort) { @@ -578,6 +599,7 @@ public: } else { + //assert(u.l.d->refCount==0); // string may not be shared when accessed raw return u.l.d->len==0 ? 0 : u.l.d->toStr(); } } @@ -645,24 +667,20 @@ public: bool fill( char c, int len ) { if (len<0) len=length(); - if (len!=(int)length()) + if (!u.s.isShort) // detach from shared string + { + resize(len+1); + } + else if (len!=(int)length()) { if (len>0) { resize(len+1); } - else - { - if (!u.s.isShort) - { - u.l.d->dispose(); - } - initEmpty(); - } } if (len>0) { - memset(data(),c,len); + memset(rawData(),c,len); } return TRUE; } diff --git a/qtools/qtextcodec.cpp b/qtools/qtextcodec.cpp index 168445f..bd874bb 100644 --- a/qtools/qtextcodec.cpp +++ b/qtools/qtextcodec.cpp @@ -1192,7 +1192,7 @@ public: lenInOut = uc.length(); int rlen = lenInOut*max_bytes_per_char; QCString rstr(rlen); - char* cursor = rstr.data(); + char* cursor = rstr.rawData(); char* s=0; int l = lenInOut; int lout = 0; @@ -1881,7 +1881,7 @@ QCString QSimpleTextCodec::fromUnicode(const QString& uc, int& len ) const int i = len; int u; const QChar* ucp = uc.unicode(); - char* rp = r.data(); + char* rp = r.rawData(); char* rmp = reverseMap->data(); int rmsize = (int) reverseMap->size(); while( i-- ) diff --git a/qtools/qtextstream.cpp b/qtools/qtextstream.cpp index bae072d..4ebf59e 100644 --- a/qtools/qtextstream.cpp +++ b/qtools/qtextstream.cpp @@ -1443,17 +1443,17 @@ QTextStream &QTextStream::operator>>( QCString &str ) if ( i >= buflen-1 ) { if ( !dynbuf ) { // create dynamic buffer dynbuf = new QCString(buflen*2); - memcpy( dynbuf->data(), s, i ); // copy old data + memcpy( dynbuf->rawData(), s, i ); // copy old data } else if ( i >= (int)dynbuf->size()-1 ) { dynbuf->resize( dynbuf->size()*2 ); } - s = dynbuf->data(); + s = dynbuf->rawData(); } s[i++] = c; c = ts_getc(); } str.resize( i+1 ); - memcpy( str.data(), s, i ); + memcpy( str.rawData(), s, i ); delete dynbuf; return *this; } diff --git a/qtools/qutfcodec.cpp b/qtools/qutfcodec.cpp index c7094ad..a37e37f 100644 --- a/qtools/qutfcodec.cpp +++ b/qtools/qutfcodec.cpp @@ -203,14 +203,14 @@ public: if ( headerdone ) { len_in_out = uc.length()*(int)sizeof(QChar); QCString d(len_in_out); - memcpy(d.data(),uc.unicode(),len_in_out); + memcpy(d.rawData(),uc.unicode(),len_in_out); return d; } else { headerdone = TRUE; len_in_out = (1+uc.length())*(int)sizeof(QChar); QCString d(len_in_out); - memcpy(d.data(),&QChar::byteOrderMark,sizeof(QChar)); - memcpy(d.data()+sizeof(QChar),uc.unicode(),uc.length()*sizeof(QChar)); + memcpy(d.rawData(),&QChar::byteOrderMark,sizeof(QChar)); + memcpy(d.rawData()+sizeof(QChar),uc.unicode(),uc.length()*sizeof(QChar)); return d; } } |