38
38
@ SuppressWarnings ("unchecked" )
39
39
public final class BufferedTokenizerExtWithSizeLimitTest extends RubyTestBase {
40
40
41
+ public static final int GB = 1024 * 1024 * 1024 ;
41
42
private BufferedTokenizerExt sut ;
42
43
private ThreadContext context ;
43
44
44
45
@ Before
45
46
public void setUp () {
47
+ initSUTWithSizeLimit (10 );
48
+ }
49
+
50
+ private void initSUTWithSizeLimit (int sizeLimit ) {
46
51
sut = new BufferedTokenizerExt (RubyUtil .RUBY , RubyUtil .BUFFERED_TOKENIZER );
47
52
context = RUBY .getCurrentContext ();
48
- IRubyObject [] args = {RubyUtil .RUBY .newString ("\n " ), RubyUtil .RUBY .newFixnum (10 )};
53
+ IRubyObject [] args = {RubyUtil .RUBY .newString ("\n " ), RubyUtil .RUBY .newFixnum (sizeLimit )};
49
54
sut .init (context , args );
50
55
}
51
56
@@ -108,4 +113,29 @@ public void giveMultipleSegmentsThatGeneratesMultipleBufferFullErrorsThenIsAbleT
108
113
RubyArray <RubyString > tokens = (RubyArray <RubyString >) sut .extract (context , RubyUtil .RUBY .newString ("ccc\n ddd\n " ));
109
114
assertEquals (List .of ("ccccc" , "ddd" ), tokens );
110
115
}
116
+
117
+ @ Test
118
+ public void givenMaliciousInputExtractDoesntOverflow () {
119
+ assertEquals ("Xmx must equals to what's defined in the Gradle's javaTests task" ,
120
+ 12L * GB , Runtime .getRuntime ().maxMemory ());
121
+
122
+ // re-init the tokenizer with big sizeLimit
123
+ initSUTWithSizeLimit ((int ) (2L * GB ) - 3 );
124
+ // Integer.MAX_VALUE is 2 * GB
125
+ String bigFirstPiece = generateString ("a" , Integer .MAX_VALUE - 1024 );
126
+ sut .extract (context , RubyUtil .RUBY .newString (bigFirstPiece ));
127
+
128
+ // add another small fragment to trigger int overflow
129
+ // sizeLimit is (2^32-1)-3 first segment length is (2^32-1) - 1024 second is 1024 +2
130
+ // so the combined length of first and second is > sizeLimit and should throw an expection
131
+ // but because of overflow it's negative and happens to be < sizeLimit
132
+ Exception thrownException = assertThrows (IllegalStateException .class , () -> {
133
+ sut .extract (context , RubyUtil .RUBY .newString (generateString ("a" , 1024 + 2 )));
134
+ });
135
+ assertThat (thrownException .getMessage (), containsString ("input buffer full" ));
136
+ }
137
+
138
+ private String generateString (String fill , int size ) {
139
+ return fill .repeat (size );
140
+ }
111
141
}
0 commit comments