View Issue Details

IDProjectCategoryView StatusLast Update
0035175LazarusTAChartpublic2019-03-02 23:51
ReporterMarcin WiazowskiAssigned Towp 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version2.1 (SVN)Product Build60555 
Target Version2.2Fixed in Version 
Summary0035175: TAChart: some additional range checks for TFitSeries
DescriptionWhen experimenting with TFitSeries, I quickly faced some random memory corruptions. Then I realized, that I unintentionally overwritten some memory by using out-of-range calls to TFitSeries.SetFitBasisFunc().

As can be seen, calls to TFitSeries.Param[] property are properly validated for out-of-range indices, but some other public methods are not validated.

So I'm attaching a patch that adds some validation to public methods. It also changes one Exception to EChartError, which seems to be more consistent with rest of the code.



Note: I used ClassName in error messages; it could be even better to use a function like "SourceClassString", that is in tasources.pas (BTW, maybe renaming it to something like "NameOrClassString" would be good).
TagsNo tags attached.
Fixed in Revision60561
LazTarget2.2
WidgetsetWin32/Win64
Attached Files
  • patch.diff (2,499 bytes)
    Index: components/tachart/tafuncseries.pas
    ===================================================================
    --- components/tachart/tafuncseries.pas	(revision 60555)
    +++ components/tachart/tafuncseries.pas	(working copy)
    @@ -1802,6 +1802,9 @@
     var
       val, sig, t: Double;
     begin
    +  if not InRange(AIndex, 0, ParamCount - 1) then
    +    raise EChartError.CreateFmt('%s.GetConfidenceLimits index out of range', [ClassName]);
    +
       if FState <> fpsValid then begin
         ALower := NaN;
         AUpper := NaN;
    @@ -1924,13 +1927,14 @@
     
     function TFitSeries.GetParam(AIndex: Integer): Double;
     begin
    +  if not InRange(AIndex, 0, ParamCount - 1) then
    +    raise EChartError.CreateFmt('%s.GetParam index out of range', [ClassName]);
    +
       if FState <> fpsValid then begin
         Result := NaN;
         exit;
       end;
     
    -  if not InRange(AIndex, 0, ParamCount - 1) then
    -    raise EChartError.Create('TFitSeries.GetParam index out of range');
       if (FFitEquation in [feExp, fePower]) and (AIndex = 0) then
         Result := exp(FFitParams[AIndex].Value)
       else
    @@ -1946,6 +1950,9 @@
     var
       val, sig: Double;
     begin
    +  if not InRange(AIndex, 0, ParamCount - 1) then
    +    raise EChartError.CreateFmt('%s.GetParamError index out of range', [ClassName]);
    +
       Result := NaN;
       if FState <> fpsValid then
         exit;
    @@ -1963,6 +1970,9 @@
     var
       t: Double;
     begin
    +  if not InRange(AIndex, 0, ParamCount - 1) then
    +    raise EChartError.CreateFmt('%s.GetParam_pValue index out of range', [ClassName]);
    +
       t := GetParam_tValue(AIndex);
       if IsNaN(t) then
         Result := NaN
    @@ -1992,6 +2002,9 @@
     var
       sig: Double;
     begin
    +  if not InRange(AIndex, 0, ParamCount - 1) then
    +    raise EChartError.CreateFmt('%s.GetParam_tValue index out of range', [ClassName]);
    +
       sig := GetParam_RawError(AIndex);
       if IsNaN(sig) then
         Result := NaN
    @@ -2117,6 +2130,9 @@
     procedure TFitSeries.SetFitBasisFunc(AIndex: TFitFuncIndex; AFitFunc: TFitFunc;
       AFitFuncName: String);
     begin
    +  if not InRange(AIndex, 0, ParamCount - 1) then
    +    raise EChartError.CreateFmt('%s.SetFitBasisFunc index out of range', [ClassName]);
    +
       FFitParams[AIndex].CustomFunc := AFitFunc;
       FFitParams[AIndex].CustomFuncName := AFitFuncName;  // e.g. 'sin(x)';
     end;
    @@ -2257,7 +2273,7 @@
                 Add(255, 0, '', clWhite);
               end;
           else
    -        raise Exception.Create('Palette not supported');
    +        raise EChartError.Create('Palette not supported');
           end;
     
           if FPaletteMin < FPaletteMax then begin
    
    patch.diff (2,499 bytes)

Activities

Marcin Wiazowski

2019-03-02 03:56

reporter  

patch.diff (2,499 bytes)
Index: components/tachart/tafuncseries.pas
===================================================================
--- components/tachart/tafuncseries.pas	(revision 60555)
+++ components/tachart/tafuncseries.pas	(working copy)
@@ -1802,6 +1802,9 @@
 var
   val, sig, t: Double;
 begin
+  if not InRange(AIndex, 0, ParamCount - 1) then
+    raise EChartError.CreateFmt('%s.GetConfidenceLimits index out of range', [ClassName]);
+
   if FState <> fpsValid then begin
     ALower := NaN;
     AUpper := NaN;
@@ -1924,13 +1927,14 @@
 
 function TFitSeries.GetParam(AIndex: Integer): Double;
 begin
+  if not InRange(AIndex, 0, ParamCount - 1) then
+    raise EChartError.CreateFmt('%s.GetParam index out of range', [ClassName]);
+
   if FState <> fpsValid then begin
     Result := NaN;
     exit;
   end;
 
-  if not InRange(AIndex, 0, ParamCount - 1) then
-    raise EChartError.Create('TFitSeries.GetParam index out of range');
   if (FFitEquation in [feExp, fePower]) and (AIndex = 0) then
     Result := exp(FFitParams[AIndex].Value)
   else
@@ -1946,6 +1950,9 @@
 var
   val, sig: Double;
 begin
+  if not InRange(AIndex, 0, ParamCount - 1) then
+    raise EChartError.CreateFmt('%s.GetParamError index out of range', [ClassName]);
+
   Result := NaN;
   if FState <> fpsValid then
     exit;
@@ -1963,6 +1970,9 @@
 var
   t: Double;
 begin
+  if not InRange(AIndex, 0, ParamCount - 1) then
+    raise EChartError.CreateFmt('%s.GetParam_pValue index out of range', [ClassName]);
+
   t := GetParam_tValue(AIndex);
   if IsNaN(t) then
     Result := NaN
@@ -1992,6 +2002,9 @@
 var
   sig: Double;
 begin
+  if not InRange(AIndex, 0, ParamCount - 1) then
+    raise EChartError.CreateFmt('%s.GetParam_tValue index out of range', [ClassName]);
+
   sig := GetParam_RawError(AIndex);
   if IsNaN(sig) then
     Result := NaN
@@ -2117,6 +2130,9 @@
 procedure TFitSeries.SetFitBasisFunc(AIndex: TFitFuncIndex; AFitFunc: TFitFunc;
   AFitFuncName: String);
 begin
+  if not InRange(AIndex, 0, ParamCount - 1) then
+    raise EChartError.CreateFmt('%s.SetFitBasisFunc index out of range', [ClassName]);
+
   FFitParams[AIndex].CustomFunc := AFitFunc;
   FFitParams[AIndex].CustomFuncName := AFitFuncName;  // e.g. 'sin(x)';
 end;
@@ -2257,7 +2273,7 @@
             Add(255, 0, '', clWhite);
           end;
       else
-        raise Exception.Create('Palette not supported');
+        raise EChartError.Create('Palette not supported');
       end;
 
       if FPaletteMin < FPaletteMax then begin
patch.diff (2,499 bytes)

wp

2019-03-02 19:51

developer   ~0114585

Applied, thanks.

Marcin Wiazowski

2019-03-02 23:51

reporter   ~0114588

Thanks!

Issue History

Date Modified Username Field Change
2019-03-02 03:56 Marcin Wiazowski New Issue
2019-03-02 03:56 Marcin Wiazowski File Added: patch.diff
2019-03-02 19:22 wp Assigned To => wp
2019-03-02 19:22 wp Status new => assigned
2019-03-02 19:51 wp Fixed in Revision => 60561
2019-03-02 19:51 wp LazTarget => 2.2
2019-03-02 19:51 wp Note Added: 0114585
2019-03-02 19:51 wp Status assigned => resolved
2019-03-02 19:51 wp Resolution open => fixed
2019-03-02 19:51 wp Target Version => 2.2
2019-03-02 23:51 Marcin Wiazowski Note Added: 0114588
2019-03-02 23:51 Marcin Wiazowski Status resolved => closed