[libreoffice/f17] Resolves: rhbz#919020 Basic CDbl() and CSng() scan localized number

Eike Rathke erack at fedoraproject.org
Mon Apr 22 18:23:14 UTC 2013


commit 16b3dedc2cd5b423f3684dae19dc9a29dcc9f940
Author: Eike Rathke <erack at redhat.com>
Date:   Mon Apr 22 20:15:50 2013 +0200

    Resolves: rhbz#919020 Basic CDbl() and CSng() scan localized number
    
    Replaces 1ca7cc38ae5cbe523a6c65b0169330ed0fd212df

 ...fixed-a-possible-crasher-in-basic-runtime.patch |  104 ------
 ...bz-919020-Basic-CDbl-and-CSng-scan-locali.patch |  341 ++++++++++++++++++++
 libreoffice.spec                                   |   13 +-
 3 files changed, 349 insertions(+), 109 deletions(-)
---
diff --git a/0001-resolved-rhbz-919020-Basic-CDbl-and-CSng-scan-locali.patch b/0001-resolved-rhbz-919020-Basic-CDbl-and-CSng-scan-locali.patch
new file mode 100644
index 0000000..cb91eae
--- /dev/null
+++ b/0001-resolved-rhbz-919020-Basic-CDbl-and-CSng-scan-locali.patch
@@ -0,0 +1,341 @@
+From 8bf4c57f57851888360736d41342abb9623480f0 Mon Sep 17 00:00:00 2001
+Message-Id: <8bf4c57f57851888360736d41342abb9623480f0.1366653663.git.erack at redhat.com>
+From: Eike Rathke <erack at redhat.com>
+Date: Tue, 19 Mar 2013 23:23:16 +0100
+Subject: [PATCH] resolved rhbz#919020 Basic CDbl() and CSng() scan localized
+ number
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="------------erAck-patch-parts"
+
+This is a multi-part message in MIME format.
+--------------erAck-patch-parts
+Content-Type: text/plain; charset=UTF-8; format=fixed
+Content-Transfer-Encoding: 8bit
+
+
+Code wrongly replaced decimal separator with '.' and used atof() to scan
+the number string which itself may be localized on *iX systems but not
+on Windows. Hence on *iX the numbers may had been truncated where on
+Windows they were not.
+
+Additionally made this work with Unicode separators if defined for the
+locale, removed the awkward conversion to ASCII byte string and
+eliminated use of toupper() and isdigit() calls. Also eliminated a
+possible buffer overflow.
+
+(cherry picked from commit 9e9f39d171cafa035d7b8e74187e25c3581cb89d)
+
+Conflicts:
+	basic/source/sbx/sbxscan.cxx
+
+replace decimal separator at correct position, rhbz#919020
+
+(cherry picked from commit e96c7a60c88bc1e3008ebdeafd59327933d6707f)
+
+Reviewed-on: https://gerrit.libreoffice.org/2859
+Reviewed-by: Noel Power <noel.power at suse.com>
+Tested-by: Noel Power <noel.power at suse.com>
+(cherry picked from commit 96b079e24f86f7f49a624573783c6e103012f942)
+
+Conflicts:
+	basic/source/sbx/sbxscan.cxx
+
+Change-Id: I35d82e8f267ecb925783bf6f2de044a29c08f688
+---
+ basic/source/sbx/sbxscan.cxx | 203 ++++++++++++++++++++++++++-----------------
+ 1 file changed, 121 insertions(+), 82 deletions(-)
+
+
+--------------erAck-patch-parts
+Content-Type: text/x-patch; name="0001-resolved-rhbz-919020-Basic-CDbl-and-CSng-scan-locali.patch"
+Content-Transfer-Encoding: 8bit
+Content-Disposition: attachment; filename="0001-resolved-rhbz-919020-Basic-CDbl-and-CSng-scan-locali.patch"
+
+diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx
+index 50e4e6c..3a0584d 100644
+--- a/basic/source/sbx/sbxscan.cxx
++++ b/basic/source/sbx/sbxscan.cxx
+@@ -62,108 +62,131 @@ void ImpGetIntntlSep( sal_Unicode& rcDecimalSep, sal_Unicode& rcThousandSep )
+     rcThousandSep = rData.getNumThousandSep().GetBuffer()[0];
+ }
+ 
++inline bool ImpIsDigit( sal_Unicode c )
++{
++    return '0' <= c && c <= '9';
++}
++
++/** NOTE: slightly differs from strchr() in that it does not consider the
++    terminating NULL character to be part of the string and returns bool
++    instead of pointer, if character is 0 returns false.
++ */
++bool ImpStrChr( const sal_Unicode* p, sal_Unicode c )
++{
++    if (!c)
++        return false;
++    while (*p)
++    {
++        if (*p++ == c)
++            return true;
++    }
++    return false;
++}
++
++bool ImpIsAlNum( sal_Unicode c )
++{
++    return (c < 128) ? isalnum( static_cast<char>(c) ) : false;
++}
++
+ // scanning a string according to BASIC-conventions
+-// but exponent may also be a D, so data type is SbxDOUBLED
++// but exponent may also be a D, so data type is SbxDOUBLE
+ // conversion error if data type is fixed and it doesn't fit
+ 
+ SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType,
+                   sal_uInt16* pLen, sal_Bool bAllowIntntl, sal_Bool bOnlyIntntl )
+ {
+-    ::rtl::OString aBStr( ::rtl::OUStringToOString( rWSrc, RTL_TEXTENCODING_ASCII_US ) );
+-
+-    char cIntntlComma, cIntntl1000;
+-    char cNonIntntlComma = '.';
+-
+-    sal_Unicode cDecimalSep, cThousandSep = 0;
++    sal_Unicode cIntntlDecSep, cIntntlGrpSep;
++    sal_Unicode cNonIntntlDecSep = '.';
+     if( bAllowIntntl || bOnlyIntntl )
+     {
+-        ImpGetIntntlSep( cDecimalSep, cThousandSep );
+-        cIntntlComma = (char)cDecimalSep;
+-        cIntntl1000 = (char)cThousandSep;
++        ImpGetIntntlSep( cIntntlDecSep, cIntntlGrpSep );
++        if( bOnlyIntntl )
++            cNonIntntlDecSep = cIntntlDecSep;
+     }
+-
+     else
+     {
+-        cIntntlComma = cNonIntntlComma;
+-        cIntntl1000 = cNonIntntlComma;
++        cIntntlDecSep = cNonIntntlDecSep;
++        cIntntlGrpSep = 0;  // no group separator accepted in non-i18n
+     }
+ 
+-    if( bOnlyIntntl )
+-    {
+-        cNonIntntlComma = cIntntlComma;
+-        cIntntl1000 = (char)cThousandSep;
+-    }
+-
+-    const char* pStart = aBStr.getStr();
+-    const char* p = pStart;
+-    char buf[ 80 ], *q = buf;
+-    sal_Bool bRes = sal_True;
+-    sal_Bool bMinus = sal_False;
++    const sal_Unicode* const pStart = rWSrc.getStr();
++    const sal_Unicode* p = pStart;
++    rtl::OUStringBuffer aBuf( rWSrc.getLength());
++    bool bRes = true;
++    bool bMinus = false;
+     nVal = 0;
+     SbxDataType eScanType = SbxSINGLE;
+-    while( *p &&( *p == ' ' || *p == '\t' ) ) p++;
++    while( *p == ' ' || *p == '\t' )
++        p++;
+     if( *p == '-' )
+-        p++, bMinus = sal_True;
+-    if( isdigit( *p ) ||( (*p == cNonIntntlComma || *p == cIntntlComma ||
+-            *p == cIntntl1000) && isdigit( *(p+1 ) ) ) )
++    {
++        p++;
++        bMinus = true;
++    }
++    if( ImpIsDigit( *p ) || ((*p == cNonIntntlDecSep || *p == cIntntlDecSep ||
++                    (cIntntlDecSep && *p == cIntntlGrpSep)) && ImpIsDigit( *(p+1) )))
+     {
+         short exp = 0;
+-        short comma = 0;
++        short decsep = 0;
+         short ndig = 0;
+         short ncdig = 0;    // number of digits after decimal point
+-        rtl::OStringBuffer aSearchStr(RTL_CONSTASCII_STRINGPARAM("0123456789DEde"));
+-        aSearchStr.append(cNonIntntlComma);
+-        if( cIntntlComma != cNonIntntlComma )
+-            aSearchStr.append(cIntntlComma);
++        rtl::OUStringBuffer aSearchStr( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("0123456789DEde")));
++        aSearchStr.append(cNonIntntlDecSep);
++        if( cIntntlDecSep != cNonIntntlDecSep )
++            aSearchStr.append(cIntntlDecSep);
+         if( bOnlyIntntl )
+-            aSearchStr.append(cIntntl1000);
+-        const char* pSearchStr = aSearchStr.getStr();
+-        while( strchr( pSearchStr, *p ) && *p )
++            aSearchStr.append(cIntntlGrpSep);
++        const sal_Unicode* const pSearchStr = aSearchStr.getStr();
++        const sal_Unicode pDdEe[] = { 'D', 'd', 'E', 'e', 0 };
++        while( ImpStrChr( pSearchStr, *p ) )
+         {
+-            if( bOnlyIntntl && *p == cIntntl1000 )
++            aBuf.append( *p );
++            if( bOnlyIntntl && *p == cIntntlGrpSep )
+             {
+                 p++;
+                 continue;
+             }
+-
+-            if( *p == cNonIntntlComma || *p == cIntntlComma )
++            if( *p == cNonIntntlDecSep || *p == cIntntlDecSep )
+             {
+-                // always insert '.' so that atof works
++                // Use the separator that is passed to stringToDouble()
++                aBuf[ p - pStart ] = cIntntlDecSep;
+                 p++;
+-                if( ++comma > 1 )
++                if( ++decsep > 1 )
+                     continue;
+-                else
+-                    *q++ = '.';
+             }
+-            else if( strchr( "DdEe", *p ) )
++            else if( ImpStrChr( pDdEe, *p ) )
+             {
+                 if( ++exp > 1 )
+                 {
+-                    p++; continue;
++                    p++;
++                    continue;
+                 }
+-                if( toupper( *p ) == 'D' )
++                if( *p == 'D' || *p == 'd' )
+                     eScanType = SbxDOUBLE;
+-                *q++ = 'E'; p++;
+-
+-                if( *p == '+' )
+-                    p++;
+-                else
+-                if( *p == '-' )
+-                    *q++ = *p++;
++                aBuf[ p - pStart ] = 'E';
++                p++;
+             }
+             else
+             {
+-                *q++ = *p++;
+-                if( comma && !exp ) ncdig++;
++                p++;
++                if( decsep && !exp )
++                    ncdig++;
+             }
+-            if( !exp ) ndig++;
++            if( !exp )
++                ndig++;
+         }
+-        *q = 0;
+ 
+-        if( comma > 1 || exp > 1 )
+-            bRes = sal_False;
++        if( decsep > 1 || exp > 1 )
++            bRes = false;
++
++        rtl::OUString aBufStr( aBuf.makeStringAndClear());
++        rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok;
++        sal_Int32 nParseEnd = 0;
++        nVal = rtl::math::stringToDouble( aBufStr, cIntntlDecSep, cIntntlGrpSep, &eStatus, &nParseEnd );
++        if( eStatus != rtl_math_ConversionStatus_Ok || nParseEnd != aBufStr.getLength() )
++            bRes = false;
+ 
+-        if( !comma && !exp )
++        if( !decsep && !exp )
+         {
+             if( nVal >= SbxMININT && nVal <= SbxMAXINT )
+                 eScanType = SbxINTEGER;
+@@ -171,49 +194,65 @@ SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType
+                 eScanType = SbxLONG;
+         }
+ 
+-        nVal = atof( buf );
+-        ndig = ndig - comma;
++        ndig = ndig - decsep;
+         // too many numbers for SINGLE?
+         if( ndig > 15 || ncdig > 6 )
+             eScanType = SbxDOUBLE;
+ 
+         // type detection?
+-        if( strchr( "%!&#", *p ) && *p ) p++;
++        const sal_Unicode pTypes[] = { '%', '!', '&', '#', 0 };
++        if( ImpStrChr( pTypes, *p ) )
++            p++;
+     }
+     // hex/octal number? read in and convert:
+     else if( *p == '&' )
+     {
+         p++;
+         eScanType = SbxLONG;
+-        const char *cmp = "0123456789ABCDEF";
++        rtl::OUString aCmp( RTL_CONSTASCII_USTRINGPARAM("0123456789ABCDEFabcdef") );
+         char base = 16;
+         char ndig = 8;
+-        char xch  = *p++;
+-        switch( toupper( xch ) )
++        switch( *p++ )
+         {
+-            case 'O': cmp = "01234567"; base = 8; ndig = 11; break;
+-            case 'H': break;
+-            default : bRes = sal_False;
++            case 'O':
++            case 'o':
++                aCmp = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("01234567"));
++                base = 8;
++                ndig = 11;
++                break;
++            case 'H':
++            case 'h':
++                break;
++            default :
++                bRes = false;
+         }
+-        long l = 0;
+-        int i;
+-        while( isalnum( *p ) )
++        const sal_Unicode* const pCmp = aCmp.getStr();
++        while( ImpIsAlNum( *p ) )    /* XXX: really munge all alnum also when error? */
+         {
+-            char ch = sal::static_int_cast< char >( toupper( *p ) );
++            sal_Unicode ch = *p;
++            if( ImpStrChr( pCmp, ch ) )
++            {
++                if (ch > 0x60)
++                    ch -= 0x20;     // convert ASCII lower to upper case
++                aBuf.append( ch );
++            }
++            else
++                bRes = false;
+             p++;
+-            if( strchr( cmp, ch ) ) *q++ = ch;
+-            else bRes = sal_False;
+         }
+-        *q = 0;
+-        for( q = buf; *q; q++ )
++        rtl::OUString aBufStr( aBuf.makeStringAndClear());
++        long l = 0;
++        for( const sal_Unicode* q = aBufStr.getStr(); bRes && *q; q++ )
+         {
+-            i =( *q & 0xFF ) - '0';
+-            if( i > 9 ) i -= 7;
+-            l =( l * base ) + i;
++            int i = *q - '0';
++            if( i > 9 )
++                i -= 7;     // 'A'-'0' = 17 => 10, ...
++            l = ( l * base ) + i;
+             if( !ndig-- )
+-                bRes = sal_False;
++                bRes = false;
+         }
+-        if( *p == '&' ) p++;
++        if( *p == '&' )
++            p++;
+         nVal = (double) l;
+         if( l >= SbxMININT && l <= SbxMAXINT )
+             eScanType = SbxINTEGER;
+
+--------------erAck-patch-parts--
+
+
diff --git a/libreoffice.spec b/libreoffice.spec
index dd9724c..3425b05 100644
--- a/libreoffice.spec
+++ b/libreoffice.spec
@@ -35,7 +35,7 @@ Summary:        Free Software Productivity Suite
 Name:           libreoffice
 Epoch:          1
 Version:        %{libo_version}.2
-Release:        11%{?dist}
+Release:        12%{?dist}
 License:        (MPLv1.1 or LGPLv3+) and LGPLv3 and LGPLv2+ and BSD and (MPLv1.1 or GPLv2 or LGPLv2 or Netscape) and Public Domain and ASL 2.0 and Artistic
 Group:          Applications/Productivity
 URL:            http://www.documentfoundation.org/develop
@@ -181,8 +181,8 @@ Patch63: 0001-Resolves-fdo-48569-crash-on-export-to-.docx-of-inlin.patch
 Patch64: 0001-rhbz-760765-copy-custom-styles-on-copy-paste.patch
 Patch65: 0001-fdo-53175-Fixed-the-end-of-hyperlinks.patch
 Patch66: 0001-Fix-fdo-47669-also-check-if-we-started-the-tag-befor.patch
-Patch67: 0001-fixed-a-possible-crasher-in-basic-runtime.patch
-Patch68: 0001-Resolves-rhbz-907933-crash-on-removing-second-last-p.patch
+Patch67: 0001-Resolves-rhbz-907933-crash-on-removing-second-last-p.patch
+Patch68: 0001-resolved-rhbz-919020-Basic-CDbl-and-CSng-scan-locali.patch
 
 %{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
 %define instdir %{_libdir}
@@ -1079,8 +1079,8 @@ mv -f redhat.soc extras/source/palettes/standard.soc
 %patch64 -p1 -b .rhbz-760765-copy-custom-styles-on-copy-paste.patch
 %patch65 -p1 -b .fdo-53175-Fixed-the-end-of-hyperlinks.patch
 %patch66 -p1 -b .Fix-fdo-47669-also-check-if-we-started-the-tag-befor.patch
-%patch67 -p1 -b .fixed-a-possible-crasher-in-basic-runtime.patch
-%patch68 -p1 -b .rhbz-907933-crash-on-removing-second-last-p.patch
+%patch67 -p1 -b .rhbz-907933-crash-on-removing-second-last-p.patch
+%patch68 -p1 -b .rhbz-919020-Basic-CDbl-and-CSng-scan-locali.patch
 
 # TODO: check this
 # these are horribly incomplete--empty translations and copied english
@@ -2367,6 +2367,9 @@ update-desktop-database %{_datadir}/applications &> /dev/null || :
 %endif
 
 %changelog
+* Mon Apr 22 2013 Eike Rathke <erack at redhat.com> - 1:3.5.7.2-12
+- Resolves: rhbz#919020 Basic CDbl() and CSng() scan localized number
+
 * Thu Apr 04 2013 Caolán McNamara <caolanm at redhat.com> - 1:3.5.7.2-11
 - Resolves: rhbz#928786 crash on deleting certain table rows
 


More information about the scm-commits mailing list