Skip to content

Commit c992f9f

Browse files
authored
Merge pull request #267 from Alexey-T/master
fix #266
2 parents db67e81 + fc80301 commit c992f9f

File tree

3 files changed

+51
-21
lines changed

3 files changed

+51
-21
lines changed

History.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@
66
(-) - bugfix
77
(^) - improvement
88

9+
v. 1.155 2022.04.28
10+
-=- (-) Fix Substitute() result for not-real group index like '$9' in regex '(b)'.
11+
By Alexey Torgashin.
12+
-=- (-) Fix UnQuoteChar() range check for Substitute() call.
13+
By @delphicz and Alexey T.
14+
915
v. 1.153 2021.07.04
1016
-=- (^) Compatability with Delphi 7. By Alexey Torgashin.
1117

src/regexpr.pas

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ TRegExpr = class
485485

486486
function HexDig(Ch: REChar): integer;
487487

488-
function UnQuoteChar(var APtr: PRegExprChar): REChar;
488+
function UnQuoteChar(var APtr, AEnd: PRegExprChar): REChar;
489489

490490
// the lowest level
491491
function ParseAtom(var FlagParse: integer): PRegExprChar;
@@ -819,7 +819,7 @@ implementation
819819
const
820820
// TRegExpr.VersionMajor/Minor return values of these constants:
821821
REVersionMajor = 1;
822-
REVersionMinor = 153;
822+
REVersionMinor = 155;
823823

824824
OpKind_End = REChar(1);
825825
OpKind_MetaClass = REChar(2);
@@ -3412,7 +3412,7 @@ function TRegExpr.HexDig(Ch: REChar): integer;
34123412
end;
34133413
end;
34143414

3415-
function TRegExpr.UnQuoteChar(var APtr: PRegExprChar): REChar;
3415+
function TRegExpr.UnQuoteChar(var APtr, AEnd: PRegExprChar): REChar;
34163416
var
34173417
Ch: REChar;
34183418
begin
@@ -3433,7 +3433,7 @@ function TRegExpr.UnQuoteChar(var APtr: PRegExprChar): REChar;
34333433
begin // \cK => code for Ctrl+K
34343434
Result := #0;
34353435
Inc(APtr);
3436-
if APtr >= fRegexEnd then
3436+
if APtr >= AEnd then
34373437
Error(reeNoLetterAfterBSlashC);
34383438
Ch := APtr^;
34393439
case Ch of
@@ -3449,7 +3449,7 @@ function TRegExpr.UnQuoteChar(var APtr: PRegExprChar): REChar;
34493449
begin // \x: hex char
34503450
Result := #0;
34513451
Inc(APtr);
3452-
if APtr >= fRegexEnd then
3452+
if APtr >= AEnd then
34533453
begin
34543454
Error(reeNoHexCodeAfterBSlashX);
34553455
Exit;
@@ -3458,7 +3458,7 @@ function TRegExpr.UnQuoteChar(var APtr: PRegExprChar): REChar;
34583458
begin // \x{nnnn} //###0.936
34593459
repeat
34603460
Inc(APtr);
3461-
if APtr >= fRegexEnd then
3461+
if APtr >= AEnd then
34623462
begin
34633463
Error(reeNoHexCodeAfterBSlashX);
34643464
Exit;
@@ -3482,7 +3482,7 @@ function TRegExpr.UnQuoteChar(var APtr: PRegExprChar): REChar;
34823482
Result := REChar(HexDig(APtr^));
34833483
// HexDig will cause Error if bad hex digit found
34843484
Inc(APtr);
3485-
if APtr >= fRegexEnd then
3485+
if APtr >= AEnd then
34863486
begin
34873487
Error(reeNoHexCodeAfterBSlashX);
34883488
Exit;
@@ -3693,7 +3693,7 @@ function TRegExpr.ParseAtom(var FlagParse: integer): PRegExprChar;
36933693
Exit;
36943694
end;
36953695
Inc(regParse);
3696-
RangeEnd := UnQuoteChar(regParse);
3696+
RangeEnd := UnQuoteChar(regParse, fRegexEnd);
36973697
end;
36983698

36993699
// special handling for Russian range a-YA, add 2 ranges: a-ya and A-YA
@@ -3764,7 +3764,7 @@ function TRegExpr.ParseAtom(var FlagParse: integer): PRegExprChar;
37643764
else
37653765
{$ENDIF}
37663766
begin
3767-
TempChar := UnQuoteChar(regParse);
3767+
TempChar := UnQuoteChar(regParse, fRegexEnd);
37683768
// False if '-' is last char in []
37693769
DashForRange :=
37703770
(regParse + 2 < fRegexEnd) and
@@ -4207,7 +4207,7 @@ function TRegExpr.ParseAtom(var FlagParse: integer): PRegExprChar;
42074207
end;
42084208
{$ENDIF}
42094209
else
4210-
EmitExactly(UnQuoteChar(regParse));
4210+
EmitExactly(UnQuoteChar(regParse, fRegexEnd));
42114211
end; { of case }
42124212
Inc(regParse);
42134213
end;
@@ -5746,10 +5746,11 @@ function TRegExpr.Substitute(const ATemplate: RegExprString): RegExprString;
57465746
APtr := p;
57475747
end;
57485748

5749-
procedure FindSubstGroupIndex(var p: PRegExprChar; var Idx: integer);
5749+
procedure FindSubstGroupIndex(var p: PRegExprChar; var Idx: integer; var NumberFound: boolean);
57505750
begin
57515751
Idx := ParseVarName(p);
5752-
if (Idx >= 0) and (Idx <= High(GrpIndexes)) then
5752+
NumberFound := (Idx >= 0) and (Idx <= High(GrpIndexes));
5753+
if NumberFound then
57535754
Idx := GrpIndexes[Idx];
57545755
end;
57555756

@@ -5760,6 +5761,7 @@ function TRegExpr.Substitute(const ATemplate: RegExprString): RegExprString;
57605761
p, p0, p1, ResultPtr: PRegExprChar;
57615762
ResultLen, n: integer;
57625763
Ch, QuotedChar: REChar;
5764+
GroupFound: boolean;
57635765
begin
57645766
// Check programm and input string
57655767
if not IsProgrammOk then
@@ -5781,11 +5783,13 @@ function TRegExpr.Substitute(const ATemplate: RegExprString): RegExprString;
57815783
Ch := p^;
57825784
Inc(p);
57835785
n := -1;
5786+
GroupFound := False;
57845787
if Ch = SubstituteGroupChar then
5785-
FindSubstGroupIndex(p, n);
5786-
if n >= 0 then
5788+
FindSubstGroupIndex(p, n, GroupFound);
5789+
if GroupFound then
57875790
begin
5788-
Inc(ResultLen, GrpEnd[n] - GrpStart[n]);
5791+
if n >= 0 then
5792+
Inc(ResultLen, GrpEnd[n] - GrpStart[n]);
57895793
end
57905794
else
57915795
begin
@@ -5836,12 +5840,18 @@ function TRegExpr.Substitute(const ATemplate: RegExprString): RegExprString;
58365840
Inc(p);
58375841
p1 := p;
58385842
n := -1;
5843+
GroupFound := False;
58395844
if Ch = SubstituteGroupChar then
5840-
FindSubstGroupIndex(p, n);
5841-
if (n >= 0) then
5845+
FindSubstGroupIndex(p, n, GroupFound);
5846+
if GroupFound then
58425847
begin
5843-
p0 := GrpStart[n];
5844-
p1 := GrpEnd[n];
5848+
if n >= 0 then
5849+
begin
5850+
p0 := GrpStart[n];
5851+
p1 := GrpEnd[n];
5852+
end
5853+
else
5854+
p1 := p0;
58455855
end
58465856
else
58475857
begin
@@ -5859,7 +5869,7 @@ function TRegExpr.Substitute(const ATemplate: RegExprString): RegExprString;
58595869
begin
58605870
p := p - 1;
58615871
// UnquoteChar expects the escaped char under the pointer
5862-
QuotedChar := UnQuoteChar(p);
5872+
QuotedChar := UnQuoteChar(p, TemplateEnd);
58635873
p := p + 1;
58645874
// Skip after last part of the escaped sequence - UnquoteChar stops on the last symbol of it
58655875
p0 := @QuotedChar;

test/tests.pas

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ TTestRegexpr= class(TTestCase)
124124
procedure RunTest67;
125125
procedure RunTest68;
126126
procedure RunTest69;
127+
procedure RunTest70;
127128
end;
128129

129130
implementation
@@ -157,7 +158,7 @@ function PrintableString(const S: RegExprString): string;
157158

158159

159160
const
160-
testCases: array [1 .. 69] of TRegExTest = (
161+
testCases: array [1 .. 70] of TRegExTest = (
161162
// 1
162163
(
163164
expression: '\nd';
@@ -709,6 +710,14 @@ function PrintableString(const S: RegExprString): string;
709710
substitutionText: '';
710711
expectedResult: '';
711712
matchStart: 1
713+
),
714+
// 70
715+
(
716+
expression: '(b)';
717+
inputText: 'abc';
718+
substitutionText: '$1$2$9';
719+
expectedResult: 'abc';
720+
matchStart: 1
712721
)
713722
);
714723

@@ -1165,6 +1174,11 @@ procedure TTestRegexpr.RunTest69;
11651174
RunRETest(69);
11661175
end;
11671176

1177+
procedure TTestRegexpr.RunTest70;
1178+
begin
1179+
RunRETest(70);
1180+
end;
1181+
11681182

11691183
procedure TTestRegexpr.TestGroups;
11701184
var

0 commit comments

Comments
 (0)