From 16b3dedc2cd5b423f3684dae19dc9a29dcc9f940 Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Apr 22 2013 18:15:50 +0000 Subject: Resolves: rhbz#919020 Basic CDbl() and CSng() scan localized number Replaces 1ca7cc38ae5cbe523a6c65b0169330ed0fd212df --- diff --git a/0001-fixed-a-possible-crasher-in-basic-runtime.patch b/0001-fixed-a-possible-crasher-in-basic-runtime.patch deleted file mode 100644 index 1fa045d..0000000 --- a/0001-fixed-a-possible-crasher-in-basic-runtime.patch +++ /dev/null @@ -1,104 +0,0 @@ -From 88a2e6260c7e5eb9d96129c7391b9ed2ba8272ba Mon Sep 17 00:00:00 2001 -Message-Id: <88a2e6260c7e5eb9d96129c7391b9ed2ba8272ba.1363951504.git.erack@redhat.com> -From: Eike Rathke -Date: Thu, 21 Mar 2013 16:34:56 +0100 -Subject: [PATCH] fixed a possible crasher -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 - - -Change-Id: I3b67ba1a8896b4b291e009b4ad680e1342ba9460 -Reviewed-on: https://gerrit.libreoffice.org/2894 -Reviewed-by: Petr Mladek -Tested-by: Petr Mladek ---- - basic/source/sbx/sbxscan.cxx | 19 +++++++++---------- - 1 file changed, 9 insertions(+), 10 deletions(-) - - ---------------erAck-patch-parts -Content-Type: text/x-patch; name="0001-fixed-a-possible-crasher.patch" -Content-Transfer-Encoding: 8bit -Content-Disposition: attachment; filename="0001-fixed-a-possible-crasher.patch" - -diff --git a/basic/source/sbx/sbxscan.cxx b/basic/source/sbx/sbxscan.cxx -index 80276a3..63f6dea 100644 ---- a/basic/source/sbx/sbxscan.cxx -+++ b/basic/source/sbx/sbxscan.cxx -@@ -97,7 +97,7 @@ SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType - - const char* pStart = aBStr.getStr(); - const char* p = pStart; -- char buf[ 80 ], *q = buf; -+ rtl::OStringBuffer aBuf( rWSrc.getLength()); - sal_Bool bRes = sal_True; - sal_Bool bMinus = sal_False; - nVal = 0; -@@ -134,7 +134,7 @@ SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType - if( ++comma > 1 ) - continue; - else -- *q++ = '.'; -+ aBuf.append('.'); - } - else if( strchr( "DdEe", *p ) ) - { -@@ -144,22 +144,21 @@ SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType - } - if( toupper( *p ) == 'D' ) - eScanType = SbxDOUBLE; -- *q++ = 'E'; p++; -+ aBuf.append('E'); p++; - - if( *p == '+' ) - p++; - else - if( *p == '-' ) -- *q++ = *p++; -+ aBuf.append( *p++ ); - } - else - { -- *q++ = *p++; -+ aBuf.append( *p++ ); - if( comma && !exp ) ncdig++; - } - if( !exp ) ndig++; - } -- *q = 0; - - if( comma > 1 || exp > 1 ) - bRes = sal_False; -@@ -172,7 +171,7 @@ SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType - eScanType = SbxLONG; - } - -- nVal = atof( buf ); -+ nVal = atof( aBuf.makeStringAndClear().getStr() ); - ndig = ndig - comma; - // too many numbers for SINGLE? - if( ndig > 15 || ncdig > 6 ) -@@ -202,11 +201,11 @@ SbxError ImpScan( const ::rtl::OUString& rWSrc, double& nVal, SbxDataType& rType - { - char ch = sal::static_int_cast< char >( toupper( *p ) ); - p++; -- if( strchr( cmp, ch ) ) *q++ = ch; -+ if( strchr( cmp, ch ) ) aBuf.append( ch ); - else bRes = sal_False; - } -- *q = 0; -- for( q = buf; *q; q++ ) -+ rtl::OString aBufStr( aBuf.makeStringAndClear()); -+ for( const sal_Char* q = aBufStr.getStr(); *q; q++ ) - { - i =( *q & 0xFF ) - '0'; - if( i > 9 ) i -= 7; - ---------------erAck-patch-parts-- - - 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@redhat.com> +From: Eike Rathke +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 +Tested-by: Noel Power +(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(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 - 1:3.5.7.2-12 +- Resolves: rhbz#919020 Basic CDbl() and CSng() scan localized number + * Thu Apr 04 2013 Caolán McNamara - 1:3.5.7.2-11 - Resolves: rhbz#928786 crash on deleting certain table rows