Skip to content

Commit 88a16d3

Browse files
committed
Avoid interop exceptions by checking if desired access is possible.
1 parent cd77f09 commit 88a16d3

File tree

1 file changed

+116
-50
lines changed

1 file changed

+116
-50
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/foreign/AccessForeignItemNodes.java

Lines changed: 116 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public Object doForeignObjectSlice(Object object, PSlice idxSlice,
126126
try {
127127
mslice = materializeSlice(idxSlice, object, lib);
128128
} catch (UnsupportedMessageException e) {
129-
throw raise(AttributeError, "%s instance has no attribute '__getitem__'", object);
129+
throw raiseAttributeError(object);
130130
}
131131
Object[] values = new Object[mslice.length];
132132
for (int i = mslice.start, j = 0; i < mslice.stop; i += mslice.step, j++) {
@@ -138,17 +138,19 @@ public Object doForeignObjectSlice(Object object, PSlice idxSlice,
138138
@Specialization
139139
public Object doForeignKey(Object object, String key,
140140
@CachedLibrary(limit = "3") InteropLibrary lib) {
141-
try {
142-
return lib.readMember(object, key);
143-
} catch (UnsupportedMessageException e) {
144-
if (lib.hasArrayElements(object)) {
145-
throw raise(TypeError, "'%p' object cannot be interpreted as an integer", key);
146-
} else {
147-
throw raise(AttributeError, "%s instance has no attribute '__getitem__'", object);
141+
if (lib.hasMembers(object)) {
142+
if (lib.isMemberReadable(object, key)) {
143+
try {
144+
return lib.readMember(object, key);
145+
} catch (UnsupportedMessageException e) {
146+
throw raiseAttributeErrorDisambiguated(object, key, lib);
147+
} catch (UnknownIdentifierException e) {
148+
// fall through
149+
}
148150
}
149-
} catch (UnknownIdentifierException e) {
150151
throw raise(KeyError, key);
151152
}
153+
throw raiseAttributeErrorDisambiguated(object, key, lib);
152154
}
153155

154156
@Specialization(guards = {"!isSlice(idx)", "!isString(idx)"})
@@ -158,14 +160,36 @@ public Object doForeignObject(Object object, Object idx,
158160
return readForeignValue(object, castIndex.execute(idx), lib);
159161
}
160162

163+
private PException raiseAttributeErrorDisambiguated(Object object, String key, InteropLibrary lib) {
164+
if (lib.hasArrayElements(object)) {
165+
throw raise(TypeError, "'%p' object cannot be interpreted as an integer", key);
166+
} else {
167+
throw raiseAttributeError(object);
168+
}
169+
}
170+
161171
private Object readForeignValue(Object object, long index, InteropLibrary lib) {
162-
try {
163-
return getToPythonNode().executeConvert(lib.readArrayElement(object, index));
164-
} catch (UnsupportedMessageException ex) {
165-
throw raise(AttributeError, "%s instance has no attribute '__getitem__'", object);
166-
} catch (InvalidArrayIndexException ex) {
167-
throw raise(IndexError, "invalid index %s", index);
172+
if (lib.hasArrayElements(object)) {
173+
if (lib.isArrayElementReadable(object, index)) {
174+
try {
175+
return getToPythonNode().executeConvert(lib.readArrayElement(object, index));
176+
} catch (UnsupportedMessageException ex) {
177+
throw raiseAttributeError(object);
178+
} catch (InvalidArrayIndexException ex) {
179+
throw raiseIndexError(index);
180+
}
181+
}
182+
throw raiseIndexError(index);
168183
}
184+
throw raiseAttributeError(object);
185+
}
186+
187+
private PException raiseIndexError(long index) {
188+
return raise(IndexError, "invalid index %s", index);
189+
}
190+
191+
private PException raiseAttributeError(Object object) {
192+
return raise(AttributeError, "%s instance has no attribute '__getitem__'", object);
169193
}
170194

171195
private PForeignToPTypeNode getToPythonNode() {
@@ -207,22 +231,40 @@ public Object doForeignObjectSlice(VirtualFrame frame, Object object, PSlice idx
207231
@Specialization
208232
public Object doForeignKey(Object object, String key, Object value,
209233
@CachedLibrary(limit = "3") InteropLibrary lib) {
210-
try {
211-
lib.writeMember(object, key, value);
212-
return PNone.NONE;
213-
} catch (UnsupportedMessageException e) {
214-
if (lib.hasArrayElements(object)) {
215-
throw raise(TypeError, "'%p' object cannot be interpreted as an integer", key);
216-
} else {
217-
throw raise(AttributeError, "attribute %s is read-only", key);
234+
if (lib.hasMembers(object)) {
235+
if (lib.isMemberWritable(object, key)) {
236+
try {
237+
lib.writeMember(object, key, value);
238+
return PNone.NONE;
239+
} catch (UnsupportedMessageException e) {
240+
throw raiseAttributeReadOnlyDisambiguated(object, key, lib);
241+
} catch (UnknownIdentifierException e) {
242+
throw raiseAttributeError(key);
243+
} catch (UnsupportedTypeException e) {
244+
throw raiseAttributeReadOnly(key);
245+
}
218246
}
219-
} catch (UnknownIdentifierException e) {
220-
throw raise(AttributeError, "foreign object has no attribute '%s'", key);
221-
} catch (UnsupportedTypeException e) {
222-
throw raise(AttributeError, "attribute %s is read-only", key);
247+
throw raiseAttributeReadOnlyDisambiguated(object, key, lib);
248+
}
249+
throw raiseAttributeError(key);
250+
}
251+
252+
private PException raiseAttributeReadOnlyDisambiguated(Object object, String key, InteropLibrary lib) {
253+
if (lib.hasArrayElements(object)) {
254+
throw raise(TypeError, "'%p' object cannot be interpreted as an integer", key);
255+
} else {
256+
throw raiseAttributeReadOnly(key);
223257
}
224258
}
225259

260+
private PException raiseAttributeReadOnly(String key) {
261+
return raise(AttributeError, "attribute %s is read-only", key);
262+
}
263+
264+
private PException raiseAttributeError(String key) {
265+
return raise(AttributeError, "foreign object has no attribute '%s'", key);
266+
}
267+
226268
@Specialization(guards = {"!isSlice(idx)", "!isString(idx)"})
227269
public Object doForeignObject(Object object, Object idx, Object value,
228270
@CachedLibrary(limit = "3") InteropLibrary lib,
@@ -239,13 +281,16 @@ public Object doForeignObject(Object object, Object idx, Object value,
239281
}
240282

241283
private void writeForeignValue(Object object, int idx, Object value, InteropLibrary lib) throws UnsupportedMessageException, UnsupportedTypeException {
242-
if (lib.isArrayElementWritable(object, idx)) {
243-
try {
244-
lib.writeArrayElement(object, idx, value);
245-
return;
246-
} catch (InvalidArrayIndexException ex) {
247-
throw raise(IndexError, "invalid index %s", idx);
284+
if (lib.hasArrayElements(object)) {
285+
if (lib.isArrayElementWritable(object, idx)) {
286+
try {
287+
lib.writeArrayElement(object, idx, value);
288+
return;
289+
} catch (InvalidArrayIndexException ex) {
290+
// fall through
291+
}
248292
}
293+
throw raise(IndexError, "invalid index %s", idx);
249294
}
250295
throw raise(AttributeError, "%s instance has no attribute '__setitem__'", object);
251296
}
@@ -270,37 +315,58 @@ public Object doForeignObjectSlice(Object object, PSlice idxSlice,
270315
}
271316
return PNone.NONE;
272317
} catch (UnsupportedMessageException e) {
273-
throw raise(AttributeError, "%s instance has no attribute '__delitem__'", object);
318+
throw raiseAttributeError(object);
274319
}
275320
}
276321

277322
@Specialization
278323
public Object doForeignKey(Object object, String key,
279324
@CachedLibrary(limit = "3") InteropLibrary lib) {
280-
try {
281-
lib.removeMember(object, key);
282-
return PNone.NONE;
283-
} catch (UnsupportedMessageException e) {
284-
if (lib.hasArrayElements(object)) {
285-
throw raise(TypeError, "'%p' object cannot be interpreted as an integer", key);
286-
} else {
287-
throw raise(AttributeError, "attribute %s is read-only", key);
325+
if (lib.hasMembers(object)) {
326+
if (lib.isMemberRemovable(object, key)) {
327+
try {
328+
lib.removeMember(object, key);
329+
return PNone.NONE;
330+
} catch (UnsupportedMessageException e) {
331+
throw raiseAttributeReadOnlyDisambiguated(object, key, lib);
332+
} catch (UnknownIdentifierException e) {
333+
throw raiseAttributeError(key);
334+
}
288335
}
289-
} catch (UnknownIdentifierException e) {
290-
throw raise(AttributeError, "foreign object has no attribute '%s'", key);
336+
throw raiseAttributeReadOnlyDisambiguated(object, key, lib);
337+
}
338+
throw raiseAttributeError(key);
339+
}
340+
341+
private PException raiseAttributeError(String key) {
342+
return raise(AttributeError, "foreign object has no attribute '%s'", key);
343+
}
344+
345+
private PException raiseAttributeReadOnlyDisambiguated(Object object, String key, InteropLibrary lib) {
346+
if (lib.hasArrayElements(object)) {
347+
throw raise(TypeError, "'%p' object cannot be interpreted as an integer", key);
348+
} else {
349+
throw raise(AttributeError, "attribute %s is read-only", key);
291350
}
292351
}
293352

294353
@Specialization(guards = "!isSlice(idx)")
295354
public Object doForeignObject(Object object, Object idx,
296355
@Cached CastToIndexNode castIndex,
297356
@CachedLibrary(limit = "3") InteropLibrary lib) {
298-
try {
299-
int convertedIdx = castIndex.execute(idx);
300-
return removeForeignValue(object, convertedIdx, lib);
301-
} catch (UnsupportedMessageException e) {
302-
throw raise(AttributeError, "%s instance has no attribute '__delitem__'", object);
357+
if (lib.hasArrayElements(object)) {
358+
try {
359+
int convertedIdx = castIndex.execute(idx);
360+
return removeForeignValue(object, convertedIdx, lib);
361+
} catch (UnsupportedMessageException e) {
362+
// fall through
363+
}
303364
}
365+
throw raiseAttributeError(object);
366+
}
367+
368+
private PException raiseAttributeError(Object object) {
369+
return raise(AttributeError, "%s instance has no attribute '__delitem__'", object);
304370
}
305371

306372
private Object removeForeignValue(Object object, int idx, InteropLibrary lib) throws UnsupportedMessageException {
@@ -311,7 +377,7 @@ private Object removeForeignValue(Object object, int idx, InteropLibrary lib) th
311377
throw raise(IndexError, "invalid index %s", idx);
312378
}
313379
}
314-
throw raise(AttributeError, "%s instance has no attribute '__delitem__'", object);
380+
throw raiseAttributeError(object);
315381
}
316382

317383
public static RemoveForeignItemNode create() {

0 commit comments

Comments
 (0)