Skip to content

Commit 70adc8a

Browse files
committed
throw correct error message when formatting a message with a tuple that is too small
1 parent ef9afca commit 70adc8a

File tree

3 files changed

+26
-13
lines changed

3 files changed

+26
-13
lines changed

graalpython/com.oracle.graal.python.test/src/tests/unittest_tags/test_binop.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
*graalpython.lib-python.3.test.test_binop.FallbackBlockingTests.test_fallback_ne_blocking
22
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_add
3+
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_constructor
34
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_div
45
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_eq
56
*graalpython.lib-python.3.test.test_binop.RatTestCase.test_floordiv

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/str/StringBuiltins.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
import com.oracle.graal.python.builtins.objects.str.StringNodes.StringLenNode;
8585
import com.oracle.graal.python.builtins.objects.str.StringUtils.StripKind;
8686
import com.oracle.graal.python.builtins.objects.tuple.PTuple;
87+
import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins;
8788
import com.oracle.graal.python.nodes.ErrorMessages;
8889
import com.oracle.graal.python.nodes.PGuards;
8990
import com.oracle.graal.python.nodes.SpecialMethodNames;
@@ -1512,10 +1513,12 @@ Object doStringObject(VirtualFrame frame, String self, Object right,
15121513
@CachedLibrary(limit = "3") PythonObjectLibrary plib,
15131514
@Shared("lookupAttrNode") @Cached LookupAttributeInMRONode.Dynamic lookupAttrNode,
15141515
@Shared("getItemNode") @Cached("create(__GETITEM__)") LookupAndCallBinaryNode getItemNode,
1516+
@Shared("getTupleItemNode") @Cached TupleBuiltins.GetItemNode getTupleItemNode,
15151517
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
15161518
Object state = IndirectCallContext.enter(frame, context, this);
15171519
try {
1518-
return new StringFormatter(context.getCore(), self).format(right, callNode, (object, key) -> lookupAttrNode.execute(plib.getLazyPythonClass(object), key), getItemNode);
1520+
return new StringFormatter(context.getCore(), self).format(right, callNode, (object, key) -> lookupAttrNode.execute(plib.getLazyPythonClass(object), key), getItemNode,
1521+
getTupleItemNode);
15191522
} finally {
15201523
IndirectCallContext.exit(frame, context, state);
15211524
}
@@ -1528,10 +1531,11 @@ Object doGeneric(VirtualFrame frame, Object self, Object right,
15281531
@CachedLibrary(limit = "3") PythonObjectLibrary plib,
15291532
@Shared("lookupAttrNode") @Cached LookupAttributeInMRONode.Dynamic lookupAttrNode,
15301533
@Shared("getItemNode") @Cached("create(__GETITEM__)") LookupAndCallBinaryNode getItemNode,
1534+
@Shared("getTupleItemNode") @Cached TupleBuiltins.GetItemNode getTupleItemNode,
15311535
@Shared("context") @CachedContext(PythonLanguage.class) PythonContext context) {
15321536

15331537
String selfStr = castSelfNode.cast(self, INVALID_RECEIVER, __MOD__, self);
1534-
return doStringObject(frame, selfStr, right, callNode, plib, lookupAttrNode, getItemNode, context);
1538+
return doStringObject(frame, selfStr, right, callNode, plib, lookupAttrNode, getItemNode, getTupleItemNode, context);
15351539
}
15361540
}
15371541

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/formatting/StringFormatter.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.oracle.graal.python.builtins.objects.ints.PInt;
2727
import com.oracle.graal.python.builtins.objects.object.PythonObjectLibrary;
2828
import com.oracle.graal.python.builtins.objects.str.PString;
29+
import com.oracle.graal.python.builtins.objects.tuple.TupleBuiltins;
2930
import com.oracle.graal.python.nodes.ErrorMessages;
3031
import com.oracle.graal.python.nodes.PGuards;
3132
import com.oracle.graal.python.nodes.call.CallNode;
@@ -67,7 +68,7 @@ public StringFormatter(PythonCore core, String format) {
6768
buffer = new StringBuilder(format.length() + 100);
6869
}
6970

70-
Object getarg(LookupAndCallBinaryNode getItemNode) {
71+
Object getarg(TupleBuiltins.GetItemNode getTupleItemNode) {
7172
Object ret = null;
7273
switch (argIndex) {
7374
case -3: // special index indicating a mapping
@@ -79,7 +80,14 @@ Object getarg(LookupAndCallBinaryNode getItemNode) {
7980
return args;
8081
default:
8182
// NOTE: passing 'null' frame means we already took care of the global state earlier
82-
ret = getItemNode.executeObject(null, args, argIndex++);
83+
// args is definitely a tuple at this point. CPython access the tuple storage
84+
// directly, so the only error can be IndexError, which we ignore and transform into
85+
// the TypeError below.
86+
try {
87+
ret = getTupleItemNode.execute(null, args, argIndex++);
88+
} catch (PException e) {
89+
// fall through
90+
}
8391
break;
8492
}
8593
if (ret == null) {
@@ -88,10 +96,10 @@ Object getarg(LookupAndCallBinaryNode getItemNode) {
8896
return ret;
8997
}
9098

91-
int getNumber(LookupAndCallBinaryNode getItemNode) {
99+
int getNumber(TupleBuiltins.GetItemNode getTupleItemNode) {
92100
char c = pop();
93101
if (c == '*') {
94-
Object o = getarg(getItemNode);
102+
Object o = getarg(getTupleItemNode);
95103
if (o instanceof Long) {
96104
return ((Long) o).intValue();
97105
} else if (o instanceof Integer) {
@@ -164,7 +172,7 @@ private static Object asFloat(Object arg, CallNode callNode, BiFunction<Object,
164172
* construction.
165173
*/
166174
@TruffleBoundary
167-
public Object format(Object args1, CallNode callNode, BiFunction<Object, String, Object> lookupAttribute, LookupAndCallBinaryNode getItemNode) {
175+
public Object format(Object args1, CallNode callNode, BiFunction<Object, String, Object> lookupAttribute, LookupAndCallBinaryNode getItemNode, TupleBuiltins.GetItemNode getTupleItemNode) {
168176
Object mapping = null;
169177
this.args = args1;
170178

@@ -272,7 +280,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
272280
* after the minimum field width and optional precision. A custom getNumber() takes care
273281
* of the '*' case.
274282
*/
275-
width = getNumber(getItemNode);
283+
width = getNumber(getTupleItemNode);
276284
if (width < 0) {
277285
width = -width;
278286
align = '<';
@@ -286,7 +294,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
286294
*/
287295
c = pop();
288296
if (c == '.') {
289-
precision = getNumber(getItemNode);
297+
precision = getNumber(getTupleItemNode);
290298
if (precision < -1) {
291299
precision = 0;
292300
}
@@ -341,7 +349,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
341349

342350
switch (spec.type) {
343351
case 'b':
344-
Object arg = getarg(getItemNode);
352+
Object arg = getarg(getTupleItemNode);
345353
f = ft = new TextFormatter(core, buffer, spec);
346354
ft.setBytes(true);
347355
Object bytesAttribute;
@@ -360,7 +368,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
360368
break;
361369
case 's': // String: converts any object using __str__(), __unicode__() ...
362370
case 'r': // ... or repr().
363-
arg = getarg(getItemNode);
371+
arg = getarg(getTupleItemNode);
364372
// Get hold of the actual object to display (may set needUnicode)
365373
Object attribute = spec.type == 's' ? lookupAttribute.apply(arg, __STR__) : lookupAttribute.apply(arg, __REPR__);
366374
if (attribute != PNone.NO_VALUE) {
@@ -383,7 +391,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
383391
case 'i': // Compatibility with scanf().
384392
// Format the argument using this Spec.
385393

386-
arg = getarg(getItemNode);
394+
arg = getarg(getTupleItemNode);
387395

388396
// Note various types accepted here as long as they have an __int__ method.
389397
Object argAsNumber = asNumber(arg, callNode, lookupAttribute);
@@ -422,7 +430,7 @@ public Object format(Object args1, CallNode callNode, BiFunction<Object, String,
422430
f = ff = new FloatFormatter(core, buffer, spec);
423431

424432
// Note various types accepted here as long as they have a __float__ method.
425-
arg = getarg(getItemNode);
433+
arg = getarg(getTupleItemNode);
426434
Object argAsFloat = asFloat(arg, callNode, lookupAttribute);
427435

428436
// We have to check what we got back..

0 commit comments

Comments
 (0)