Skip to content

Commit 66bcb69

Browse files
makenowjustkkos
andauthored
Port Oniguruma patches to prevent integer overflow (ruby#14027)
* Port a Oniguruma patch: Integer overflow in forward_search_range() kkos/oniguruma@db64ef3 Co-Authored-By: K.Kosako <[email protected]> * Port a Oniguruma patch: Integer overflow in backward_search_range() and onig_search_gpos() kkos/oniguruma@bfc36d3 Co-Authored-By: K.Kosako <[email protected]> * Port a Oniguruma patch: Integer overflow in onig_search_gpos() kkos/oniguruma@778a43d It differs from the Oniguruma patch in that it dosen't use `onigenc_get_prev_char_head()` because this function's signature has been changed by Oniguruma and the change is not ported in Onigmo for now. This patch respects the current Onigmo implementation. Co-Authored-By: K.Kosako <[email protected]> * Add castings to prevent warnings * Correct castings to use OnigDistance --------- Co-authored-by: K.Kosako <[email protected]>
1 parent cbe5241 commit 66bcb69

File tree

1 file changed

+69
-31
lines changed

1 file changed

+69
-31
lines changed

regexec.c

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4959,14 +4959,14 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
49594959
}
49604960

49614961
p = s;
4962-
if (reg->dmin > 0) {
4962+
if (reg->dmin != 0) {
4963+
if ((OnigDistance)(end - p) <= reg->dmin) return 0; /* fail */
49634964
if (ONIGENC_IS_SINGLEBYTE(reg->enc)) {
49644965
p += reg->dmin;
49654966
}
49664967
else {
49674968
UChar *q = p + reg->dmin;
49684969

4969-
if (q >= end) return 0; /* fail */
49704970
while (p < q) p += enclen(reg->enc, p, end);
49714971
}
49724972
}
@@ -5003,7 +5003,7 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
50035003
}
50045004

50055005
if (p && p < range) {
5006-
if (p - reg->dmin < s) {
5006+
if ((OnigDistance)(p - s) < reg->dmin) {
50075007
retry_gate:
50085008
pprev = p;
50095009
p += enclen(reg->enc, p, end);
@@ -5047,10 +5047,11 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
50475047
*low_prev = onigenc_get_prev_char_head(reg->enc,
50485048
(pprev ? pprev : str), p, end);
50495049
}
5050+
*high = p;
50505051
}
50515052
else {
50525053
if (reg->dmax != ONIG_INFINITE_DISTANCE) {
5053-
if (p < str + reg->dmax) {
5054+
if ((OnigDistance)(p - str) < reg->dmax) {
50545055
*low = (UChar* )str;
50555056
if (low_prev)
50565057
*low_prev = onigenc_get_prev_char_head(reg->enc, str, *low, end);
@@ -5071,9 +5072,12 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
50715072
}
50725073
}
50735074
}
5075+
/* no needs to adjust *high, *high is used as range check only */
5076+
if ((OnigDistance)(p - str) < reg->dmin)
5077+
*high = (UChar* )str;
5078+
else
5079+
*high = p - reg->dmin;
50745080
}
5075-
/* no needs to adjust *high, *high is used as range check only */
5076-
*high = p - reg->dmin;
50775081

50785082
#ifdef ONIG_DEBUG_SEARCH
50795083
fprintf(stderr,
@@ -5100,7 +5104,6 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
51005104
return 0;
51015105
}
51025106

5103-
range += reg->dmin;
51045107
p = s;
51055108

51065109
retry:
@@ -5178,10 +5181,22 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
51785181
}
51795182
}
51805183

5181-
/* no needs to adjust *high, *high is used as range check only */
51825184
if (reg->dmax != ONIG_INFINITE_DISTANCE) {
5183-
*low = p - reg->dmax;
5184-
*high = p - reg->dmin;
5185+
if ((OnigDistance)(p - str) < reg->dmax)
5186+
*low = (UChar* )str;
5187+
else
5188+
*low = p - reg->dmax;
5189+
5190+
if (reg->dmin != 0) {
5191+
if ((OnigDistance)(p - str) < reg->dmin)
5192+
*high = (UChar* )str;
5193+
else
5194+
*high = p - reg->dmin;
5195+
}
5196+
else {
5197+
*high = p;
5198+
}
5199+
51855200
*high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high, end);
51865201
}
51875202

@@ -5340,30 +5355,37 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
53405355
min_semi_end = max_semi_end = (UChar* )end;
53415356

53425357
end_buf:
5343-
if ((OnigDistance )(max_semi_end - str) < reg->anchor_dmin)
5358+
if ((OnigDistance)(max_semi_end - str) < reg->anchor_dmin)
53445359
goto mismatch_no_msa;
53455360

53465361
if (range > start) {
5347-
if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) {
5362+
if ((OnigDistance)(min_semi_end - start) > reg->anchor_dmax) {
53485363
start = min_semi_end - reg->anchor_dmax;
53495364
if (start < end)
53505365
start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
53515366
}
5352-
if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
5353-
range = max_semi_end - reg->anchor_dmin + 1;
5367+
if ((OnigDistance)(max_semi_end - (range - 1)) < reg->anchor_dmin) {
5368+
if ((OnigDistance)(max_semi_end - str + 1) < reg->anchor_dmin)
5369+
goto mismatch_no_msa;
5370+
else
5371+
range = max_semi_end - reg->anchor_dmin + 1;
53545372
}
53555373

53565374
if (start > range) goto mismatch_no_msa;
53575375
/* If start == range, match with empty at end.
53585376
Backward search is used. */
53595377
}
53605378
else {
5361-
if ((OnigDistance )(min_semi_end - range) > reg->anchor_dmax) {
5379+
if ((OnigDistance)(min_semi_end - range) > reg->anchor_dmax) {
53625380
range = min_semi_end - reg->anchor_dmax;
53635381
}
5364-
if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {
5365-
start = max_semi_end - reg->anchor_dmin;
5366-
start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
5382+
if ((OnigDistance)(max_semi_end - start) < reg->anchor_dmin) {
5383+
if ((OnigDistance)(max_semi_end - str) < reg->anchor_dmin)
5384+
goto mismatch_no_msa;
5385+
else {
5386+
start = max_semi_end - reg->anchor_dmin;
5387+
start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
5388+
}
53675389
}
53685390
if (range > start) goto mismatch_no_msa;
53695391
}
@@ -5442,15 +5464,19 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
54425464
if (reg->optimize != ONIG_OPTIMIZE_NONE) {
54435465
UChar *sch_range, *low, *high, *low_prev;
54445466

5445-
sch_range = (UChar* )range;
54465467
if (reg->dmax != 0) {
54475468
if (reg->dmax == ONIG_INFINITE_DISTANCE)
54485469
sch_range = (UChar* )end;
54495470
else {
5450-
sch_range += reg->dmax;
5451-
if (sch_range > end) sch_range = (UChar* )end;
5471+
if ((OnigDistance)(end - range) < reg->dmax)
5472+
sch_range = (UChar* )end;
5473+
else {
5474+
sch_range = (UChar* )range + reg->dmax;
5475+
}
54525476
}
54535477
}
5478+
else
5479+
sch_range = (UChar* )range;
54545480

54555481
if ((end - start) < reg->threshold_len)
54565482
goto mismatch;
@@ -5507,18 +5533,27 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
55075533
else { /* backward search */
55085534
if (reg->optimize != ONIG_OPTIMIZE_NONE) {
55095535
UChar *low, *high, *adjrange, *sch_start;
5536+
const UChar *min_range;
55105537

55115538
if (range < end)
55125539
adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range, end);
55135540
else
55145541
adjrange = (UChar* )end;
55155542

5543+
if ((OnigDistance)(end - range) > reg->dmin)
5544+
min_range = range + reg->dmin;
5545+
else
5546+
min_range = end;
5547+
55165548
if (reg->dmax != ONIG_INFINITE_DISTANCE &&
5517-
(end - range) >= reg->threshold_len) {
5549+
end - range >= reg->threshold_len) {
55185550
do {
5519-
sch_start = s + reg->dmax;
5520-
if (sch_start > end) sch_start = (UChar* )end;
5521-
if (backward_search_range(reg, str, end, sch_start, range, adjrange,
5551+
if ((OnigDistance)(end - s) > reg->dmax)
5552+
sch_start = s + reg->dmax;
5553+
else
5554+
sch_start = (UChar* )end;
5555+
5556+
if (backward_search_range(reg, str, end, sch_start, min_range, adjrange,
55225557
&low, &high) <= 0)
55235558
goto mismatch;
55245559

@@ -5534,21 +5569,24 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
55345569
goto mismatch;
55355570
}
55365571
else { /* check only. */
5537-
if ((end - range) < reg->threshold_len) goto mismatch;
5572+
if (end - range < reg->threshold_len) goto mismatch;
55385573

5539-
sch_start = s;
55405574
if (reg->dmax != 0) {
55415575
if (reg->dmax == ONIG_INFINITE_DISTANCE)
55425576
sch_start = (UChar* )end;
55435577
else {
5544-
sch_start += reg->dmax;
5545-
if (sch_start > end) sch_start = (UChar* )end;
5546-
else
5578+
if ((OnigDistance)(end - s) > reg->dmax) {
5579+
sch_start = s + reg->dmax;
55475580
sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
55485581
start, sch_start, end);
5582+
} else
5583+
sch_start = (UChar* )end;
55495584
}
55505585
}
5551-
if (backward_search_range(reg, str, end, sch_start, range, adjrange,
5586+
else
5587+
sch_start = (UChar* )s;
5588+
5589+
if (backward_search_range(reg, str, end, sch_start, min_range, adjrange,
55525590
&low, &high) <= 0) goto mismatch;
55535591
}
55545592
}

0 commit comments

Comments
 (0)