Skip to content

Commit 8c0250b

Browse files
committed
rtlib: wstring concat and assign buffer overrun
- When using concatenate and assign operator &= on fixed length wstring buffer, the null terminator can be overwritten causing a buffer overrun on a subsequent operation. - fixed using fb_wstr_copy() which explicitly writes the null terminator - tests added
1 parent 12beda0 commit 8c0250b

File tree

3 files changed

+67
-3
lines changed

3 files changed

+67
-3
lines changed

changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ Version 1.07.0
2121
- sf.net #899: TRIM( wstring ) causes crash if string is single space
2222
- sf.net #900: LTRIM( wstring, filter ) and TRIM( wstring, filter ) truncate result if filter is zero length string
2323
- github #116: Fix optimizations in [L/R]TrimAny rtlib functions (SkyFish)
24+
- github #145: WSTRING concat and assign buffer (&=) overrun
2425

2526

2627
Version 1.06.0

src/rtlib/strw_concatassign.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ FBCALL FB_WCHAR *fb_WstrConcatAssign( FB_WCHAR *dst, ssize_t dst_chars, const FB
1919
/* don't check ptr's */
2020
if( dst_chars > 0 )
2121
{
22-
--dst_chars; /* less the null-term */
22+
/* less the null-term */
23+
--dst_chars;
2324

2425
if( src_len > dst_chars - dst_len )
2526
src_len = dst_chars - dst_len;
27+
28+
fb_wstr_Copy( &dst[dst_len], src, src_len );
2629
}
2730

28-
/* copy the null-term too */
29-
fb_wstr_Move( &dst[dst_len], src, src_len + 1 );
3031

3132
return dst;
3233
}

tests/wstring/concat-assign.bas

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#include "fbcunit.bi"
2+
#include "chk-wstring.bi"
3+
4+
SUITE( fbc_tests.wstring_.concat_assign )
5+
6+
#macro check( len_a, len_b, count, s )
7+
scope
8+
dim a as wstring * len_a
9+
dim b as wstring * len_b = s
10+
dim r as wstring * 100
11+
for i as integer = 1 to count
12+
13+
'' concat & assign
14+
a &= b
15+
16+
'' concat, truncate, assign
17+
r = left( r & b, len_a - 1 )
18+
19+
CU_ASSERT_WSTRING_EQUAL( a, r )
20+
next
21+
end scope
22+
#endmacro
23+
24+
#macro check_6( len_b, count, s )
25+
check( 1, 2, 4, s )
26+
check( 2, 2, 4, s )
27+
check( 3, 2, 4, s )
28+
check( 4, 2, 4, s )
29+
check( 5, 2, 4, s )
30+
check( 6, 2, 4, s )
31+
#endmacro
32+
33+
TEST( default )
34+
35+
'' strings converted to wstring
36+
check( 1, 1, 1, "a" )
37+
check( 1, 1, 2, "a" )
38+
39+
check_6( 2, 4, "a" )
40+
check_6( 3, 4, "ab" )
41+
42+
check_6( 4, 4, "ab" )
43+
check_6( 5, 4, "ab" )
44+
45+
check_6( 4, 4, "abc" )
46+
check_6( 5, 4, "abc" )
47+
48+
'' wstrings
49+
check( 1, 1, 1, !"\u3041" )
50+
check( 1, 1, 2, !"\u3041" )
51+
52+
check_6( 2, 4, !"\u3041" )
53+
check_6( 3, 4, !"\u3041\u3043" )
54+
55+
check_6( 4, 4, !"\u3041\u3043" )
56+
check_6( 5, 4, !"\u3041\u3043" )
57+
58+
check_6( 4, 4, !"\u3041\u3043\u3045" )
59+
check_6( 5, 4, !"\u3041\u3043\u3045" )
60+
END_TEST
61+
62+
END_SUITE

0 commit comments

Comments
 (0)