Skip to content

Commit 5e8bf30

Browse files
authored
Merge pull request #133 from toddr-bot/koan.toddr.bot/fix-base60-buffer-underflow
fix: prevent buffer underflow in base60 parsing
2 parents f5646aa + 208a4d3 commit 5e8bf30

3 files changed

Lines changed: 59 additions & 10 deletions

File tree

MANIFEST

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ t/bug/doesnt-stringify.t
3636
t/bug/rt-41141.t
3737
t/bug/rt-49404-double_free.t
3838
t/bug/rt-54167.t
39+
t/gh-132-base60-safety.t
3940
t/json-basic.t
4041
t/json-circular-ref.t
4142
t/json-crlf.t

perl_syck.h

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,16 +195,20 @@ yaml_syck_parser_handler
195195
{
196196
NV bnum = 0;
197197
char *colon = end - 1;
198-
while ( colon >= ptr && *colon != ':' )
198+
while ( colon > ptr && *colon != ':' )
199199
{
200200
colon--;
201201
}
202-
if ( *colon == ':' ) *colon = '\0';
203-
204-
bnum = strtod( colon + 1, NULL );
202+
if ( *colon == ':' ) {
203+
*colon = '\0';
204+
bnum = strtod( colon + 1, NULL );
205+
end = colon;
206+
} else {
207+
bnum = strtod( ptr, NULL );
208+
end = ptr;
209+
}
205210
total += bnum * sixty;
206211
sixty *= 60;
207-
end = colon;
208212
}
209213
sv = newSVnv(total);
210214
#ifdef NV_NAN
@@ -233,16 +237,20 @@ yaml_syck_parser_handler
233237
{
234238
long bnum = 0;
235239
char *colon = end - 1;
236-
while ( colon >= ptr && *colon != ':' )
240+
while ( colon > ptr && *colon != ':' )
237241
{
238242
colon--;
239243
}
240-
if ( *colon == ':' ) *colon = '\0';
241-
242-
bnum = strtol( colon + 1, NULL, 10 );
244+
if ( *colon == ':' ) {
245+
*colon = '\0';
246+
bnum = strtol( colon + 1, NULL, 10 );
247+
end = colon;
248+
} else {
249+
bnum = strtol( ptr, NULL, 10 );
250+
end = ptr;
251+
}
243252
total += bnum * sixty;
244253
sixty *= 60;
245-
end = colon;
246254
}
247255
sv = newSVuv(total);
248256
} else if (strEQ( id, "int#hex" )) {

t/gh-132-base60-safety.t

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use strict;
2+
use warnings;
3+
4+
use FindBin;
5+
BEGIN { push @INC, $FindBin::Bin }
6+
7+
use TestYAML ();
8+
use Test::More tests => 10;
9+
use YAML::Syck qw(Load);
10+
11+
# GH #132 - base60 (sexagesimal) parsing safety
12+
# The parser walked a pointer before the start of the buffer when
13+
# processing the leftmost segment of a base-60 value. Verify that
14+
# int#base60 and float#base60 produce correct results and do not
15+
# crash or read out-of-bounds.
16+
17+
$YAML::Syck::ImplicitTyping = 1;
18+
19+
# --- int#base60 ---
20+
is( Load("--- 1:0:0\n"), 3600, "int base60: 1:0:0 = 3600" );
21+
is( Load("--- 1:30:45\n"), 5445, "int base60: 1:30:45 = 5445" );
22+
is( Load("--- 0:30\n"), 30, "int base60: 0:30 = 30" );
23+
is( Load("--- 0:0\n"), 0, "int base60: 0:0 = 0" );
24+
25+
# --- float#base60 ---
26+
is( Load("--- 1:30:45.5\n"), 5445.5, "float base60: 1:30:45.5 = 5445.5" );
27+
is( Load("--- 0:0.5\n"), 0.5, "float base60: 0:0.5 = 0.5" );
28+
29+
# --- edge cases: single-colon values ---
30+
is( Load("--- 59:59\n"), 3599, "int base60: 59:59 = 3599" );
31+
32+
# --- multi-segment ---
33+
is( Load("--- 1:2:3:4\n"), 223384, "int base60: 1:2:3:4 = 1*216000+2*3600+3*60+4" );
34+
35+
# --- negative base60 (parsed as string, not base60 - verify no crash) ---
36+
my $neg = Load("--- -1:30\n");
37+
ok( defined $neg, "negative sexagesimal loads without crash" );
38+
39+
# --- large segment count (stress the loop) ---
40+
is( Load("--- 1:0:0:0\n"), 216000, "int base60: 1:0:0:0 = 216000" );

0 commit comments

Comments
 (0)