diff options
-rw-r--r-- | fpdfsdk/src/javascript/Field.cpp | 22 | ||||
-rw-r--r-- | fpdfsdk/src/javascript/PublicMethods.cpp | 153 | ||||
-rw-r--r-- | fpdfsdk/src/javascript/PublicMethods.h | 9 | ||||
-rw-r--r-- | testing/resources/javascript/bug_361_expected.txt | 32 |
4 files changed, 172 insertions, 44 deletions
diff --git a/fpdfsdk/src/javascript/Field.cpp b/fpdfsdk/src/javascript/Field.cpp index ebd3d331f5..959e8dcadd 100644 --- a/fpdfsdk/src/javascript/Field.cpp +++ b/fpdfsdk/src/javascript/Field.cpp @@ -2741,8 +2741,13 @@ FX_BOOL Field::value(IJS_Context* cc, CFX_WideString swValue = pFormField->GetValue(); double dRet; - if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) { - vp << dRet; + FX_BOOL bDot; + if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet, + bDot)) { + if (bDot) + vp << dRet; + else + vp << dRet; } else { vp << swValue; } @@ -2764,8 +2769,13 @@ FX_BOOL Field::value(IJS_Context* cc, CFX_WideString swValue = pFormField->GetValue(); double dRet; - if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) { - vp << dRet; + FX_BOOL bDot; + if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet, + bDot)) { + if (bDot) + vp << dRet; + else + vp << dRet; } else { vp << swValue; } @@ -2780,7 +2790,9 @@ FX_BOOL Field::value(IJS_Context* cc, CFX_WideString swValue = pFormField->GetControl(i)->GetExportValue(); double dRet; - if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet)) { + FX_BOOL bDotDummy; + if (CJS_PublicMethods::ConvertStringToNumber(swValue.c_str(), dRet, + bDotDummy)) { vp << dRet; } else { vp << swValue; diff --git a/fpdfsdk/src/javascript/PublicMethods.cpp b/fpdfsdk/src/javascript/PublicMethods.cpp index 9e5ad5d182..d2f7fb09ac 100644 --- a/fpdfsdk/src/javascript/PublicMethods.cpp +++ b/fpdfsdk/src/javascript/PublicMethods.cpp @@ -194,38 +194,147 @@ CFX_ByteString CJS_PublicMethods::StrTrim(const FX_CHAR* pStr) { return StrRTrim(StrLTrim(pStr)); } -FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource, - double& dRet) { - CFX_ByteString sDigits = CFX_WideString(swSource).UTF8Encode(); +double CJS_PublicMethods::ParseNumber(const FX_WCHAR* swSource, + FX_BOOL& bAllDigits, + FX_BOOL& bDot, + FX_BOOL& bSign, + FX_BOOL& bKXJS) { + bDot = FALSE; + bSign = FALSE; + bKXJS = FALSE; + + FX_BOOL bDigitExist = FALSE; + + const FX_WCHAR* p = swSource; + wchar_t c; - // Always interpret "," as "." independent of the locale. - for (FX_STRSIZE k = 0; k < sDigits.GetLength(); k++) { - if (sDigits[k] == ',') - sDigits.SetAt(k, '.'); + const FX_WCHAR* pStart = NULL; + const FX_WCHAR* pEnd = NULL; + + while ((c = *p)) { + if (!pStart && c != L' ') { + pStart = p; + } + + pEnd = p; + p++; } - // Parse a number, ignoring leading and trailing whitespace. - // Fail if there is trailing garbage. - const char* pStart = sDigits.c_str(); - const char* pEnd = NULL; - dRet = strtod(pStart, const_cast<char**>(&pEnd)); - if (pEnd == pStart) { - return FALSE; + if (!pStart) { + bAllDigits = FALSE; + return 0; } - for (; *pEnd; pEnd++) { - if (!isspace(*pEnd)) { - dRet = 0; - return FALSE; + + while (pEnd != pStart) { + if (*pEnd == L' ') + pEnd--; + else + break; + } + + double dRet = 0; + p = pStart; + bAllDigits = TRUE; + CFX_WideString swDigits; + + while (p <= pEnd) { + c = *p; + + if (FXSYS_iswdigit(c)) { + swDigits += c; + bDigitExist = TRUE; + } else { + switch (c) { + case L' ': + bAllDigits = FALSE; + break; + case L'.': + case L',': + if (!bDot) { + if (bDigitExist) { + swDigits += L'.'; + } else { + swDigits += L'0'; + swDigits += L'.'; + bDigitExist = TRUE; + } + + bDot = TRUE; + break; + } + case 'e': + case 'E': + if (!bKXJS) { + p++; + c = *p; + if (c == '+' || c == '-') { + bKXJS = TRUE; + swDigits += 'e'; + swDigits += c; + } + break; + } + case L'-': + if (!bDigitExist && !bSign) { + swDigits += c; + bSign = TRUE; + break; + } + default: + bAllDigits = FALSE; + + if (p != pStart && !bDot && bDigitExist) { + swDigits += L'.'; + bDot = TRUE; + } else { + bDot = FALSE; + bDigitExist = FALSE; + swDigits = L""; + } + break; + } } + + p++; } - return TRUE; + if (swDigits.GetLength() > 0 && swDigits.GetLength() < 17) { + CFX_ByteString sDigits = swDigits.UTF8Encode(); + + if (bKXJS) { + dRet = atof(sDigits); + } else { + if (bDot) { + char* pStopString; + dRet = ::strtod(sDigits, &pStopString); + } else { + dRet = atol(sDigits); + } + } + } + + return dRet; } double CJS_PublicMethods::ParseStringToNumber(const FX_WCHAR* swSource) { - double dRet; - ConvertStringToNumber(swSource, dRet); - return dRet; + FX_BOOL bAllDigits = FALSE; + FX_BOOL bDot = FALSE; + FX_BOOL bSign = FALSE; + FX_BOOL bKXJS = FALSE; + + return ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS); +} + +FX_BOOL CJS_PublicMethods::ConvertStringToNumber(const FX_WCHAR* swSource, + double& dRet, + FX_BOOL& bDot) { + FX_BOOL bAllDigits = FALSE; + FX_BOOL bSign = FALSE; + FX_BOOL bKXJS = FALSE; + + dRet = ParseNumber(swSource, bAllDigits, bDot, bSign, bKXJS); + + return bAllDigits; } CJS_Array CJS_PublicMethods::AF_MakeArrayFromList(CJS_Runtime* pRuntime, diff --git a/fpdfsdk/src/javascript/PublicMethods.h b/fpdfsdk/src/javascript/PublicMethods.h index 0172cbafb8..013c4ce1a4 100644 --- a/fpdfsdk/src/javascript/PublicMethods.h +++ b/fpdfsdk/src/javascript/PublicMethods.h @@ -144,11 +144,18 @@ class CJS_PublicMethods : public CJS_Object { bool* bWrongFormat); static CFX_WideString MakeFormatDate(double dDate, const CFX_WideString& format); - static FX_BOOL ConvertStringToNumber(const FX_WCHAR* swSource, double& dRet); + static FX_BOOL ConvertStringToNumber(const FX_WCHAR* swSource, + double& dRet, + FX_BOOL& bDot); static double ParseStringToNumber(const FX_WCHAR* swSource); static double ParseNormalDate(const CFX_WideString& value, bool* bWrongFormat); static double MakeInterDate(CFX_WideString strValue); + static double ParseNumber(const FX_WCHAR* swSource, + FX_BOOL& bAllDigits, + FX_BOOL& bDot, + FX_BOOL& bSign, + FX_BOOL& bKXJS); public: static CFX_WideString StrLTrim(const FX_WCHAR* pStr); diff --git a/testing/resources/javascript/bug_361_expected.txt b/testing/resources/javascript/bug_361_expected.txt index da9256277f..f7f7a562bb 100644 --- a/testing/resources/javascript/bug_361_expected.txt +++ b/testing/resources/javascript/bug_361_expected.txt @@ -12,31 +12,31 @@ Alert: Answer for " 4 Alert: Answer for "4 3 2 1" is: string 4 3 2 1 Alert: Answer for "-4" is: number -4 Alert: Answer for "23.00000001" is: number 23.00000001 -Alert: Answer for "23.00000000000000001" is: number 23 +Alert: Answer for "23.00000000000000001" is: number 0 Alert: Answer for "4e+25" is: number 4e+25 -Alert: Answer for "40000000000000000000000000" is: number 4e+25 +Alert: Answer for "40000000000000000000000000" is: number 0 Alert: Answer for "25,5" is: number 25.5 Alert: Answer for "1e+5" is: number 100000 -Alert: Answer for "1e5" is: number 100000 +Alert: Answer for "1e5" is: number 1 Alert: Answer for "1e-5" is: number 0.00001 Alert: Answer for "-1e-5" is: number -0.00001 -Alert: Answer for "1.2e5" is: number 120000 -Alert: Answer for "Infinity" is: number Infinity -Alert: Answer for "Infinity" is: number Infinity -Alert: Answer for "INFINITY" is: number Infinity -Alert: Answer for "INF" is: number Infinity -Alert: Answer for "NaN" is: number NaN -Alert: Answer for "NaN" is: number NaN -Alert: Answer for "NAN" is: number NaN -Alert: Answer for "0x100" is: number 256 -Alert: Answer for "0x100.1" is: number 256.0625 -Alert: Answer for "0x100,1" is: number 256.0625 +Alert: Answer for "1.2e5" is: number 1.2 +Alert: Answer for "Infinity" is: string Infinity +Alert: Answer for "Infinity" is: string Infinity +Alert: Answer for "INFINITY" is: string INFINITY +Alert: Answer for "INF" is: string INF +Alert: Answer for "NaN" is: string NaN +Alert: Answer for "NaN" is: string NaN +Alert: Answer for "NAN" is: string NAN +Alert: Answer for "0x100" is: string 0x100 +Alert: Answer for "0x100.1" is: string 0x100.1 +Alert: Answer for "0x100,1" is: string 0x100,1 Alert: Answer for "0x100x1" is: string 0x100x1 Alert: Answer for "123x6" is: string 123x6 Alert: Answer for "123xy6" is: string 123xy6 Alert: Answer for "123.y6" is: string 123.y6 -Alert: Answer for "1,000,000" is: string 1,000,000 -Alert: Answer for "1.2.3" is: string 1.2.3 +Alert: Answer for "1,000,000" is: number 1 +Alert: Answer for "1.2.3" is: number 1.2 Alert: Answer for "1-3" is: string 1-3 Alert: Answer for "1+3" is: string 1+3 Alert: Answer for "1.-3" is: string 1.-3 |