]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/fileconf.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / fileconf.cpp
index c0164655351877ff801e11425a139947e0468f4f..4b632703207d402ca81e7a81a9c48931aa394fc7 100644 (file)
@@ -46,7 +46,7 @@
 
 #include  "wx/stdpaths.h"
 
-#if defined(__WXMSW__)
+#if defined(__WINDOWS__)
     #include "wx/msw/private.h"
 #endif  //windows.h
 #if defined(__WXPM__)
 #include  <stdlib.h>
 #include  <ctype.h>
 
-// ----------------------------------------------------------------------------
-// macros
-// ----------------------------------------------------------------------------
-#define CONST_CAST ((wxFileConfig *)this)->
-
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
@@ -151,7 +146,7 @@ private:
 
   wxString      m_strName,      // entry name
                 m_strValue;     //       value
-  bool          m_bImmutable:1, // can be overriden locally?
+  bool          m_bImmutable:1, // can be overridden locally?
                 m_bHasValue:1;  // set after first call to SetValue()
 
   int           m_nLine;        // used if m_pLine == NULL only
@@ -474,32 +469,35 @@ wxFileConfig::wxFileConfig(wxInputStream &inStream, const wxMBConv& conv)
     cbuf = wxCharBuffer::CreateNonOwned((char *)buf.GetData(), buf.GetDataLen());
 #endif // wxUSE_UNICODE/!wxUSE_UNICODE
 
-
-    // now break it into lines
-    wxMemoryText memText;
-    for ( const wxChar *s = cbuf; ; ++s )
+    // parse the input contents if there is anything to parse
+    if ( cbuf )
     {
-        const wxChar *e = s;
-        while ( *e != '\0' && *e != '\n' && *e != '\r' )
-            ++e;
+        // now break it into lines
+        wxMemoryText memText;
+        for ( const wxChar *s = cbuf; ; ++s )
+        {
+            const wxChar *e = s;
+            while ( *e != '\0' && *e != '\n' && *e != '\r' )
+                ++e;
 
-        // notice that we throw away the original EOL kind here, maybe we
-        // should preserve it?
-        if ( e != s )
-            memText.AddLine(wxString(s, e));
+            // notice that we throw away the original EOL kind here, maybe we
+            // should preserve it?
+            if ( e != s )
+                memText.AddLine(wxString(s, e));
 
-        if ( *e == '\0' )
-            break;
+            if ( *e == '\0' )
+                break;
 
-        // skip the second EOL byte if it's a DOS one
-        if ( *e == '\r' && e[1] == '\n' )
-            ++e;
+            // skip the second EOL byte if it's a DOS one
+            if ( *e == '\r' && e[1] == '\n' )
+                ++e;
 
-        s = e;
-    }
+            s = e;
+        }
 
-    // Finally we can parse it all.
-    Parse(memText, true /* local */);
+        // Finally we can parse it all.
+        Parse(memText, true /* local */);
+    }
 
     SetRootPath();
     ResetDirty();
@@ -663,7 +661,7 @@ void wxFileConfig::Parse(const wxTextBuffer& buffer, bool bLocal)
           // which is exactly what we want.
           else if ( !bLocal || pEntry->IsLocal() ) {
             wxLogWarning(_("file '%s', line %d: key '%s' was first found at line %d."),
-                         buffer.GetName(), n + 1, strKey.c_str(), pEntry->Line());
+                         buffer.GetName(), (int)n + 1, strKey.c_str(), pEntry->Line());
 
           }
         }
@@ -791,12 +789,14 @@ size_t wxFileConfig::GetNumberOfEntries(bool bRecursive) const
 {
     size_t n = m_pCurrentGroup->Entries().GetCount();
     if ( bRecursive ) {
+        wxFileConfig * const self = const_cast<wxFileConfig *>(this);
+
         wxFileConfigGroup *pOldCurrentGroup = m_pCurrentGroup;
         size_t nSubgroups = m_pCurrentGroup->Groups().GetCount();
         for ( size_t nGroup = 0; nGroup < nSubgroups; nGroup++ ) {
-            CONST_CAST m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
+            self->m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
             n += GetNumberOfEntries(true);
-            CONST_CAST m_pCurrentGroup = pOldCurrentGroup;
+            self->m_pCurrentGroup = pOldCurrentGroup;
         }
     }
 
@@ -807,12 +807,14 @@ size_t wxFileConfig::GetNumberOfGroups(bool bRecursive) const
 {
     size_t n = m_pCurrentGroup->Groups().GetCount();
     if ( bRecursive ) {
+        wxFileConfig * const self = const_cast<wxFileConfig *>(this);
+
         wxFileConfigGroup *pOldCurrentGroup = m_pCurrentGroup;
         size_t nSubgroups = m_pCurrentGroup->Groups().GetCount();
         for ( size_t nGroup = 0; nGroup < nSubgroups; nGroup++ ) {
-            CONST_CAST m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
+            self->m_pCurrentGroup = m_pCurrentGroup->Groups()[nGroup];
             n += GetNumberOfGroups(true);
-            CONST_CAST m_pCurrentGroup = pOldCurrentGroup;
+            self->m_pCurrentGroup = pOldCurrentGroup;
         }
     }
 
@@ -1816,6 +1818,11 @@ bool wxFileConfigGroup::DeleteEntry(const wxString& name)
       // pNewLast can be NULL here -- it's ok and can happen if we have no
       // entries left
       m_pLastEntry = pNewLast;
+
+      // For the root group only, we could be removing the first group line
+      // here, so update m_pLine to avoid keeping a dangling pointer.
+      if ( pLine == m_pLine )
+          SetLine(NULL);
     }
 
     m_pConfig->LineListRemove(pLine);
@@ -2109,7 +2116,7 @@ static wxString FilterOutEntryName(const wxString& str)
 #if !wxUSE_UNICODE
             ((unsigned char)c < 127) &&
 #endif // ANSI
-         !wxIsalnum(c) && !wxStrchr(wxT("@_/-!.*%"), c) )
+         !wxIsalnum(c) && !wxStrchr(wxT("@_/-!.*%()"), c) )
     {
       strResult += wxT('\\');
     }