TAChart: Avoid crash when XCount and/or YCount of a chart source is changed to illegal value while attached to a series. Issue #35089, patch by Marcin Wiazowski

git-svn-id: trunk@60464 -
This commit is contained in:
wp 2019-02-20 06:31:02 +00:00
parent a949be0aee
commit bb30af0ea0
15 changed files with 102 additions and 23 deletions

View File

@ -396,9 +396,15 @@ msgid "Right triangle"
msgstr "Dreieck nach rechs"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
#, fuzzy
#| msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr "%0:s benötigt eine Datenquelle mit mindestens %1:d %2:s Wert(en) pro Datenpunkt."
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol
msgid "Star (lines)"
msgstr "Stern (Linien)"

View File

@ -384,7 +384,11 @@ msgid "Right triangle"
msgstr ""
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -394,7 +394,11 @@ msgid "Right triangle"
msgstr "Triangle à droite"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -394,7 +394,11 @@ msgid "Right triangle"
msgstr "Háromszög (jobbra)"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -395,7 +395,11 @@ msgid "Right triangle"
msgstr "Trikampis dešinėn"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -393,7 +393,11 @@ msgid "Right triangle"
msgstr ""
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -384,7 +384,11 @@ msgid "Right triangle"
msgstr ""
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -394,7 +394,11 @@ msgid "Right triangle"
msgstr "Triângulo direito"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -394,9 +394,13 @@ msgid "Right triangle"
msgstr "Треугольник с вершиной справа"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr "%0:s требуется источник данных для диаграммы, имеющий не менее следующего количества значений в величине: %1:d по оси %2:s."
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol
msgid "Star (lines)"
msgstr "Звезда (из линий)"

View File

@ -397,7 +397,11 @@ msgid "Right triangle"
msgstr ""
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -397,9 +397,13 @@ msgid "Right triangle"
msgstr "Трикутник з вершиною праворуч"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr "%0:s потребує джерела діаграми з принаймні %1:d %2:s значенням(и) на точку даних."
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol
msgid "Star (lines)"
msgstr "Зірка (з ліній)"

View File

@ -395,7 +395,11 @@ msgid "Right triangle"
msgstr "直角三角形"
#: tachartstrconsts.rssourcecounterror
msgid "%0:s requires a chart source with at least %1:d %2:s value(s) per data point."
msgid "%0:s requires a chart source with at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rssourcecounterror2
msgid "This %0:s instance must have at least %1:d \"%2:s\" value(s) per data point."
msgstr ""
#: tachartstrconsts.rsstarsymbol

View File

@ -69,7 +69,8 @@ resourcestring
rsDistanceMeasurement = 'Distance measurement';
// Chart sources
rsSourceCountError = '%0:s requires a chart source with at least %1:d %2:s value(s) per data point.';
rsSourceCountError = '%0:s requires a chart source with at least %1:d "%2:s" value(s) per data point.';
rsSourceCountError2 = 'This %0:s instance must have at least %1:d "%2:s" value(s) per data point.';
// Transformations
tasAxisTransformsEditorTitle = 'Edit axis transformations';

View File

@ -788,9 +788,9 @@ begin
exit;
GetXYCountNeeded(nx, ny);
if ASource.XCount < nx then
raise EXCountError.CreateFmt(rsSourceCountError, [ClassName, nx, 'x'])
else if ASource.YCount < ny then
raise EYCountError.CreateFmt(rsSourceCountError, [ClassName, ny, 'y']);
raise EXCountError.CreateFmt(rsSourceCountError, [ClassName, nx, 'X']);
if ASource.YCount < ny then
raise EYCountError.CreateFmt(rsSourceCountError, [ClassName, ny, 'Y']);
end;
procedure TChartSeries.Clear;
@ -817,11 +817,9 @@ begin
inherited Create(AOwner);
FListener := TListener.Create(@FSource, @SourceChanged);
FBuiltinSource := TListChartSource.Create(Self);
FBuiltinSource.Name := BUILTIN_SOURCE_NAME;
GetXYCountNeeded(nx, ny);
FBuiltinSource.XCount := nx;
FBuiltinSource.YCount := ny;
FBuiltinSource := TListChartSource.Create(Self, nx, ny);
FBuiltinSource.Name := BUILTIN_SOURCE_NAME;
FBuiltinSource.Broadcaster.Subscribe(FListener);
FMarks := TChartMarks.Create(FChart);
FStylesListener := TListener.Create(@FStyles, @StyleChanged);
@ -1125,7 +1123,12 @@ end;
procedure TChartSeries.SourceChanged(ASender: TObject);
begin
if ASender is TCustomChartSource then
CheckSource(TCustomChartSource(ASender));
try
CheckSource(TCustomChartSource(ASender));
except
Source := nil; // revert to built-in source
raise;
end;
StyleChanged(ASender);
end;

View File

@ -23,6 +23,8 @@ type
TListChartSource = class(TCustomChartSource)
private
FXCountMin: Cardinal;
FYCountMin: Cardinal;
FData: TFPList;
FDataPoints: TStrings;
FSorted: Boolean;
@ -44,7 +46,8 @@ type
EXListEmptyError = class(EChartError);
EYListEmptyError = class(EChartError);
public
constructor Create(AOwner: TComponent); override;
constructor Create(AOwner: TComponent); override; overload;
constructor Create(AOwner: TComponent; AXCountMin, AYCountMin: Cardinal); overload;
destructor Destroy; override;
public
function Add(
@ -247,7 +250,7 @@ procedure Register;
implementation
uses
Math, StrUtils, SysUtils, TAMath;
Math, StrUtils, SysUtils, TAMath, TAChartStrConsts;
type
@ -467,6 +470,11 @@ procedure TListChartSource.CopyFrom(ASource: TCustomChartSource);
var
i: Integer;
begin
if ASource.XCount < FXCountMin then
raise EXCountError.CreateFmt(rsSourceCountError2, [ClassName, FXCountMin, 'X']);
if ASource.YCount < FYCountMin then
raise EYCountError.CreateFmt(rsSourceCountError2, [ClassName, FYCountMin, 'Y']);
BeginUpdate;
try
Clear;
@ -492,6 +500,17 @@ begin
ClearCaches;
end;
constructor TListChartSource.Create(AOwner: TComponent; AXCountMin, AYCountMin: Cardinal);
begin
Create(AOwner);
FXCountMin := AXCountMin;
FYCountMin := AYCountMin;
if FXCount < FXCountMin then
FXCount := FXCountMin;
if FYCount < FYCountMin then
FYCount := FYCountMin;
end;
procedure TListChartSource.Delete(AIndex: Integer);
begin
with Item[AIndex]^ do begin
@ -580,10 +599,13 @@ procedure TListChartSource.SetXCount(AValue: Cardinal);
var
i: Integer;
begin
if AValue < FXCountMin then
raise EXCountError.CreateFmt(rsSourceCountError2, [ClassName, FXCountMin, 'X']);
if AValue = FXCount then exit;
FXCount := AValue;
for i := 0 to Count - 1 do
SetLength(Item[i]^.XList, Max(FXCount - 1, 0));
Notify;
end;
procedure TListChartSource.SetXList(
@ -654,10 +676,13 @@ procedure TListChartSource.SetYCount(AValue: Cardinal);
var
i: Integer;
begin
if AValue < FYCountMin then
raise EYCountError.CreateFmt(rsSourceCountError2, [ClassName, FYCountMin, 'Y']);
if AValue = FYCount then exit;
FYCount := AValue;
for i := 0 to Count - 1 do
SetLength(Item[i]^.YList, Max(FYCount - 1, 0));
Notify;
end;
procedure TListChartSource.SetYList(