Skip to content

Commit a32a9ec

Browse files
committed
Handle overflows and memory errors in encoding/decoding
1 parent 84105bf commit a32a9ec

File tree

1 file changed

+54
-24
lines changed

1 file changed

+54
-24
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/CodecsModuleBuiltins.java

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
package com.oracle.graal.python.builtins.modules;
4242

4343
import static com.oracle.graal.python.runtime.exception.PythonErrorType.LookupError;
44+
import static com.oracle.graal.python.runtime.exception.PythonErrorType.MemoryError;
4445
import static com.oracle.graal.python.runtime.exception.PythonErrorType.TypeError;
4546
import static com.oracle.graal.python.runtime.exception.PythonErrorType.UnicodeDecodeError;
4647
import static com.oracle.graal.python.runtime.exception.PythonErrorType.UnicodeEncodeError;
@@ -143,22 +144,27 @@ void handle(TruffleEncoder encoder, String errorAction, Object inputObject,
143144
@Cached("createIdentityProfile()") ValueProfile actionProfile,
144145
@Cached RaiseEncodingErrorNode raiseEncodingErrorNode,
145146
@Cached PRaiseNode raiseNode) {
146-
// Ignore and replace are handled by Java Charset
147-
switch (actionProfile.profile(errorAction)) {
148-
case STRICT:
149-
break;
150-
case BACKSLASHREPLACE:
151-
if (backslashreplace(encoder)) {
152-
return;
153-
}
154-
break;
155-
case SURROGATEPASS:
156-
if (surrogatepass(encoder)) {
157-
return;
158-
}
159-
break;
160-
default:
161-
raiseNode.raise(LookupError, ErrorMessages.UNKNOWN_ERROR_HANDLER, errorAction);
147+
try {
148+
// Ignore and replace are handled by Java Charset
149+
switch (actionProfile.profile(errorAction)) {
150+
case STRICT:
151+
break;
152+
case BACKSLASHREPLACE:
153+
if (backslashreplace(encoder)) {
154+
return;
155+
}
156+
break;
157+
case SURROGATEPASS:
158+
if (surrogatepass(encoder)) {
159+
return;
160+
}
161+
break;
162+
default:
163+
raiseNode.raise(LookupError, ErrorMessages.UNKNOWN_ERROR_HANDLER, errorAction);
164+
}
165+
} catch (OutOfMemoryError e) {
166+
CompilerDirectives.transferToInterpreterAndInvalidate();
167+
throw raiseNode.raise(MemoryError);
162168
}
163169
throw raiseEncodingErrorNode.execute(encoder, inputObject);
164170
}
@@ -401,9 +407,15 @@ private PBytes encodeString(Object self, String input, String encoding, String e
401407
if (charset == null) {
402408
throw raise(LookupError, ErrorMessages.UNKNOWN_ENCODING, encoding);
403409
}
404-
TruffleEncoder encoder = new TruffleEncoder(CharsetMapping.normalize(encoding), charset, input, errorAction);
405-
while (!encoder.encodingStep()) {
406-
handleEncodingError(encoder, errors, self);
410+
TruffleEncoder encoder;
411+
try {
412+
encoder = new TruffleEncoder(CharsetMapping.normalize(encoding), charset, input, errorAction);
413+
while (!encoder.encodingStep()) {
414+
handleEncodingError(encoder, errors, self);
415+
}
416+
} catch (OutOfMemoryError e) {
417+
CompilerDirectives.transferToInterpreterAndInvalidate();
418+
throw raise(MemoryError);
407419
}
408420
return factory().createBytes(encoder.getBytes());
409421
}
@@ -466,9 +478,15 @@ Object decodeBytes(PBytesLike input, String encoding, String errors, boolean fin
466478
if (charset == null) {
467479
throw raise(LookupError, ErrorMessages.UNKNOWN_ENCODING, encoding);
468480
}
469-
TruffleDecoder decoder = new TruffleDecoder(CharsetMapping.normalize(encoding), charset, bytes, errorAction);
470-
while (!decoder.decodingStep(finalData)) {
471-
handleDecodingError(decoder, errors, input);
481+
TruffleDecoder decoder;
482+
try {
483+
decoder = new TruffleDecoder(CharsetMapping.normalize(encoding), charset, bytes, errorAction);
484+
while (!decoder.decodingStep(finalData)) {
485+
handleDecodingError(decoder, errors, input);
486+
}
487+
} catch (OutOfMemoryError e) {
488+
CompilerDirectives.transferToInterpreterAndInvalidate();
489+
throw raise(MemoryError);
472490
}
473491
return factory().createTuple(new Object[]{decoder.getString(), decoder.getInputPosition()});
474492
}
@@ -597,7 +615,13 @@ public boolean encodingStep() {
597615
}
598616

599617
private void grow() {
600-
ByteBuffer newBuffer = ByteBuffer.allocate(2 * outputBuffer.capacity() + 1);
618+
int newCapacity = 2 * outputBuffer.capacity() + 1;
619+
// Overflow check - (2 * Integer.MAX_VALUE + 1 == -1) => overflown result cannot be
620+
// positive
621+
if (newCapacity < 0) {
622+
throw new OutOfMemoryError();
623+
}
624+
ByteBuffer newBuffer = ByteBuffer.allocate(newCapacity);
601625
outputBuffer.flip();
602626
newBuffer.put(outputBuffer);
603627
outputBuffer = newBuffer;
@@ -706,7 +730,13 @@ public boolean decodingStep(boolean finalData) {
706730
}
707731

708732
private void grow() {
709-
CharBuffer newBuffer = CharBuffer.allocate(2 * outputBuffer.capacity() + 1);
733+
int newCapacity = 2 * outputBuffer.capacity() + 1;
734+
// Overflow check - (2 * Integer.MAX_VALUE + 1 == -1) => overflown result cannot be
735+
// positive
736+
if (newCapacity < 0) {
737+
throw new OutOfMemoryError();
738+
}
739+
CharBuffer newBuffer = CharBuffer.allocate(newCapacity);
710740
outputBuffer.flip();
711741
newBuffer.put(outputBuffer);
712742
outputBuffer = newBuffer;

0 commit comments

Comments
 (0)