]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/xlocale.cpp
fixing overrelease and out-of-bounds write, fixes #13725
[wxWidgets.git] / src / common / xlocale.cpp
index b2b035aed19af79b86999f53d1833cc8465bc07d..d0197463f802cd6ad11a7296ccf3cc462f409384 100644 (file)
@@ -31,6 +31,9 @@
 
 #include "wx/xlocale.h"
 
+#include <errno.h>
+#include <locale.h>
+
 // ----------------------------------------------------------------------------
 // module globals
 // ----------------------------------------------------------------------------
@@ -74,7 +77,9 @@ wxXLocale& wxXLocale::GetCLocale()
 {
     if ( !gs_cLocale )
     {
-        gs_cLocale = new wxXLocale(static_cast<wxXLocaleCTag *>(NULL));
+        // NOTE: bcc551 has trouble doing static_cast with incomplete
+        //       type definition. reinterpret_cast used as workaround
+        gs_cLocale = new wxXLocale( reinterpret_cast<wxXLocaleCTag *>(NULL) );
     }
 
     return *gs_cLocale;
@@ -134,24 +139,24 @@ void wxXLocale::Init(const char *loc)
         wxString buf(loc);
         wxString buf2;
         buf2 = buf + wxS(".UTF-8");
-        m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
+        m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
         if ( !m_locale )
         {
             buf2 = buf + wxS(".utf-8");
-            m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
+            m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
         }
         if ( !m_locale )
         {
             buf2 = buf + wxS(".UTF8");
-            m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
+            m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
         }
         if ( !m_locale )
         {
             buf2 = buf + wxS(".utf8");
-            m_locale = newlocale(LC_ALL_MASK, buf2, NULL);
+            m_locale = newlocale(LC_ALL_MASK, buf2.c_str(), NULL);
         }
     }
-    
+
     // TODO: wxLocale performs many more manipulations of the given locale
     //       string in the attempt to set a valid locale; reusing that code
     //       (changing it to take a generic wxTryLocale callback) would be nice
@@ -192,7 +197,7 @@ void wxXLocale::Free()
 #define CTYPE_UPPER 0x0200
 #define CTYPE_XDIGIT 0x0400
 
-static unsigned int gs_lookup[] =
+static const unsigned int gs_lookup[] =
 {
     0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
     0x0004, 0x0104, 0x0104, 0x0104, 0x0104, 0x0104, 0x0004, 0x0004,
@@ -260,6 +265,106 @@ int wxToupper_l(const wxUniChar& c, const wxXLocale& loc)
     return c;
 }
 
+
+// ----------------------------------------------------------------------------
+// string --> number conversion functions
+// ----------------------------------------------------------------------------
+
+/*
+    WARNING: the implementation of the wxStrtoX_l() functions below is unsafe
+             in a multi-threaded environment as we temporary change the locale
+             and if in the meanwhile an other thread performs some locale-dependent
+             operation, it may get unexpected results...
+             However this is the best we can do without reinventing the wheel in the
+             case !wxHAS_XLOCALE_SUPPORT...
+*/
+
+namespace
+{
+
+// Helper class that changes LC_NUMERIC facet of the global locale in its ctor
+// to "C" locale and restores it in its dtor later.
+class CNumericLocaleSetter
+{
+public:
+    CNumericLocaleSetter()
+        : m_oldLocale(wxStrdupA(setlocale(LC_NUMERIC, NULL)))
+    {
+        if ( !wxSetlocale(LC_NUMERIC, "C") )
+        {
+            // Setting locale to "C" should really always work.
+            wxFAIL_MSG( wxS("Couldn't set LC_NUMERIC to \"C\"") );
+        }
+    }
+
+    ~CNumericLocaleSetter()
+    {
+        wxSetlocale(LC_NUMERIC, m_oldLocale);
+        free(m_oldLocale);
+    }
+
+private:
+    char * const m_oldLocale;
+
+    wxDECLARE_NO_COPY_CLASS(CNumericLocaleSetter);
+};
+
+} // anonymous namespace
+
+double wxStrtod_l(const wchar_t* str, wchar_t **endptr, const wxXLocale& loc)
+{
+    wxCHECK( loc.IsOk(), 0. );
+
+    CNumericLocaleSetter locSetter;
+
+    return wxStrtod(str, endptr);
+}
+
+double wxStrtod_l(const char* str, char **endptr, const wxXLocale& loc)
+{
+    wxCHECK( loc.IsOk(), 0. );
+
+    CNumericLocaleSetter locSetter;
+
+    return wxStrtod(str, endptr);
+}
+
+long wxStrtol_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
+{
+    wxCHECK( loc.IsOk(), 0 );
+
+    CNumericLocaleSetter locSetter;
+
+    return wxStrtol(str, endptr, base);
+}
+
+long wxStrtol_l(const char* str, char **endptr, int base, const wxXLocale& loc)
+{
+    wxCHECK( loc.IsOk(), 0 );
+
+    CNumericLocaleSetter locSetter;
+
+    return wxStrtol(str, endptr, base);
+}
+
+unsigned long wxStrtoul_l(const wchar_t* str, wchar_t **endptr, int base, const wxXLocale& loc)
+{
+    wxCHECK( loc.IsOk(), 0 );
+
+    CNumericLocaleSetter locSetter;
+
+    return wxStrtoul(str, endptr, base);
+}
+
+unsigned long wxStrtoul_l(const char* str, char **endptr, int base, const wxXLocale& loc)
+{
+    wxCHECK( loc.IsOk(), 0 );
+
+    CNumericLocaleSetter locSetter;
+
+    return wxStrtoul(str, endptr, base);
+}
+
 #endif // !defined(wxHAS_XLOCALE_SUPPORT)
 
 #endif // wxUSE_XLOCALE