From 2a25a3e64cdc3a7f8c6e20424b01c134411a89ae Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Wed, 13 Apr 2016 10:03:47 +0000 Subject: [PATCH] fpspreadsheet: Fix range overflow if formula contains integers > 65535 git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@4619 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- components/fpspreadsheet/fpsexprparser.pas | 10 ++++------ components/fpspreadsheet/fpsrpn.pas | 6 +++--- components/fpspreadsheet/fpstypes.pas | 2 +- components/fpspreadsheet/xlscommon.pas | 15 +++++++++++---- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/components/fpspreadsheet/fpsexprparser.pas b/components/fpspreadsheet/fpsexprparser.pas index f21d77b9e..98da59f9e 100644 --- a/components/fpspreadsheet/fpsexprparser.pas +++ b/components/fpspreadsheet/fpsexprparser.pas @@ -1601,12 +1601,10 @@ begin if TryStrToInt64(CurrentToken, I) then Result := TsConstExprNode.CreateInteger(self, I) else - begin - if TryStrToFloat(CurrentToken, X, FFormatSettings) then - Result := TsConstExprNode.CreateFloat(self, X) - else - ParserError(Format(rsInvalidFloat, [CurrentToken])); - end; + if TryStrToFloat(CurrentToken, X, FFormatSettings) then + Result := TsConstExprNode.CreateFloat(self, X) + else + ParserError(Format(rsInvalidFloat, [CurrentToken])); end else if (TokenType = ttTrue) then Result := TsConstExprNode.CreateBoolean(self, true) diff --git a/components/fpspreadsheet/fpsrpn.pas b/components/fpspreadsheet/fpsrpn.pas index bf50ea0b5..fadc46bb5 100644 --- a/components/fpspreadsheet/fpsrpn.pas +++ b/components/fpspreadsheet/fpsrpn.pas @@ -56,7 +56,7 @@ function RPNCellRef3D(ASheet, ARow, ACol: Integer; AFlags: TsRelFlags; function RPNCellRange3D(ASheet1, ARow1, ACol1, ASheet2, ARow2, ACol2: Integer; AFlags: TsRelFlags; ANext: PRPNItem): PRPNItem; function RPNErr(AErrCode: TsErrorValue; ANext: PRPNItem): PRPNItem; -function RPNInteger(AValue: Word; ANext: PRPNItem): PRPNItem; +function RPNInteger(AValue: Int64; ANext: PRPNItem): PRPNItem; function RPNMissingArg(ANext: PRPNItem): PRPNItem; function RPNNumber(AValue: Double; ANext: PRPNItem): PRPNItem; function RPNParenthesis(ANext: PRPNItem): PRPNItem; @@ -299,12 +299,12 @@ begin end; {@@ ---------------------------------------------------------------------------- - Creates an entry in the RPN array for a 2-byte unsigned integer + Creates an entry in the RPN array for an integer value @param AValue Integer value to be inserted into the formula @param ANext Pointer to the next RPN item in the list -------------------------------------------------------------------------------} -function RPNInteger(AValue: Word; ANext: PRPNItem): PRPNItem; +function RPNInteger(AValue: Int64; ANext: PRPNItem): PRPNItem; begin Result := NewRPNItem; Result^.FE.ElementKind := fekInteger; diff --git a/components/fpspreadsheet/fpstypes.pas b/components/fpspreadsheet/fpstypes.pas index 3be872f39..2512788ab 100644 --- a/components/fpspreadsheet/fpstypes.pas +++ b/components/fpspreadsheet/fpstypes.pas @@ -202,7 +202,7 @@ type Sheet, Sheet2: Integer; // zero-based SheetNames: String; // both sheet names separated by a TAB character (intermediate use only) DoubleValue: double; - IntValue: Word; + IntValue: Int64; StringValue: String; RelFlags: TsRelFlags; // info on relative/absolute addresses FuncName: String; diff --git a/components/fpspreadsheet/xlscommon.pas b/components/fpspreadsheet/xlscommon.pas index 372865aff..19bb8f0da 100644 --- a/components/fpspreadsheet/xlscommon.pas +++ b/components/fpspreadsheet/xlscommon.pas @@ -585,10 +585,6 @@ type const AFormula: TsRPNFormula; ACell: PCell); virtual; function WriteRPNFunc(AStream: TStream; AIdentifier: Word): Word; virtual; procedure WriteRPNResult(AStream: TStream; ACell: PCell); - { - procedure WriteRPNSharedFormulaLink(AStream: TStream; ACell: PCell; - var RPNLength: Word); virtual; - } procedure WriteRPNTokenArray(AStream: TStream; ACell: PCell; const AFormula: TsRPNFormula; UseRelAddr, IsSupported: Boolean; var RPNLength: Word); procedure WriteRPNTokenArraySize(AStream: TStream; ASize: Word); virtual; @@ -4110,6 +4106,17 @@ begin INT_EXCEL_TOKEN_TAREA_A : primaryExcelCode := INT_EXCEL_TOKEN_TAREAN_A; end; + // Excel BIFF uses only 2-byte integers. + // --> Convert larger values to float. + // Note: only positive values have to be considered because negative values + // have an additional unary minus token. + if (primaryExcelCode = INT_EXCEL_TOKEN_TINT) and + (AFormula[i].IntValue > word($FFFF)) then + begin + primaryExcelCode := INT_EXCEL_TOKEN_TNUM; + AFormula[i].DoubleValue := 1.0*AFormula[i].IntValue; + end; + AStream.WriteByte(primaryExcelCode); inc(RPNLength);