From a6e7a80d0835430bcdee980fa5566d3dca14cb5e Mon Sep 17 00:00:00 2001 From: Raffi Khatchadourian Date: Wed, 27 May 2026 18:29:45 -0400 Subject: [PATCH] Handle `IOException` locally in `TensorType.shapeArg`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `shapeArg` declared `throws IOException` because `new SourceBuffer(p)` inside the body can throw when the underlying source file is unavailable (e.g. for a synthetic / detached `Position`). The two direct callers in `PythonTensorAnalysisEngine` and the indirect caller `handleShapeSourceOp` then wrapped the exception as `RuntimeException`, which just crashed the analysis with no useful information. Catch `IOException` inside `shapeArg` instead, log at `FINE`, and fall through to the symbolic-dim fallback already present further down the loop — graceful degradation instead of analysis abort. Drop the now-unnecessary `throws IOException` clause on `shapeArg` and `handleShapeSourceOp`, and the `try/catch (IOException)` wrappers in `getShapeSourceCalls`, `getSetShapeCallsSyntactic`, and the two `handleShapeSourceOp` call sites. Also drop the two `System.err.println` debug prints in the `shapeArg` source-buffer block. Fixes https://github.com/wala/ML/issues/555. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ml/client/PythonTensorAnalysisEngine.java | 53 ++++++------------- .../wala/cast/python/ml/types/TensorType.java | 23 ++++---- 2 files changed, 31 insertions(+), 45 deletions(-) diff --git a/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/client/PythonTensorAnalysisEngine.java b/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/client/PythonTensorAnalysisEngine.java index 82fbee46a..0c1138401 100644 --- a/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/client/PythonTensorAnalysisEngine.java +++ b/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/client/PythonTensorAnalysisEngine.java @@ -62,7 +62,6 @@ import com.ibm.wala.util.intset.IntSet; import com.ibm.wala.util.intset.OrdinalSet; import java.io.File; -import java.io.IOException; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -751,20 +750,16 @@ private Map getShapeSourceCalls( op, builder, (CGNode src, SSAAbstractInvokeInstruction call) -> { - try { - if (call.getNumberOfUses() > param) - targets.put( - builder - .getPropagationSystem() - .findOrCreatePointsToSet( - builder - .getPointerAnalysis() - .getHeapModel() - .getPointerKeyForLocal(src, call.getDef())), - TensorType.shapeArg(src, call.getUse(param))); - } catch (IOException e) { - throw new RuntimeException("Error while processing shape source call: " + call, e); - } + if (call.getNumberOfUses() > param) + targets.put( + builder + .getPropagationSystem() + .findOrCreatePointsToSet( + builder + .getPointerAnalysis() + .getHeapModel() + .getPointerKeyForLocal(src, call.getDef())), + TensorType.shapeArg(src, call.getUse(param))); }); return targets; } @@ -856,13 +851,9 @@ private Map getSetShapeCallsSyntactic( } } if (!receiverEligible) continue; - try { - targets.put( - builder.getPropagationSystem().findOrCreatePointsToSet(receiverKey), - TensorType.shapeArg(caller, call.getUse(1))); - } catch (IOException e) { - throw new RuntimeException("Error while processing set_shape call: " + call, e); - } + targets.put( + builder.getPropagationSystem().findOrCreatePointsToSet(receiverKey), + TensorType.shapeArg(caller, call.getUse(1))); } } return targets; @@ -971,12 +962,8 @@ public TensorTypeAnalysis performAnalysis(PropagationCallGraphBuilder builder) for (PointsToSetVariable v : sources) init.put(v, getTensorTypes(v, builder)); - Map placeholders = null; - try { - placeholders = handleShapeSourceOp(builder, dataflow, placeholder, 2); - } catch (IOException e) { - throw new RuntimeException("Error while processing placeholder calls.", e); - } + Map placeholders = + handleShapeSourceOp(builder, dataflow, placeholder, 2); LOGGER.fine("Placeholders: " + placeholders); for (Map.Entry e : placeholders.entrySet()) @@ -1015,12 +1002,7 @@ public TensorTypeAnalysis performAnalysis(PropagationCallGraphBuilder builder) } Map shapeOps = HashMapFactory.make(); - - try { - shapeOps.putAll(handleShapeSourceOp(builder, dataflow, reshape, 2)); - } catch (IOException e) { - throw new RuntimeException("Error while processing reshape calls.", e); - } + shapeOps.putAll(handleShapeSourceOp(builder, dataflow, reshape, 2)); handlePassThroughOp(builder, dataflow, convert_to_tensor, 1); @@ -1098,8 +1080,7 @@ private Map handleShapeSourceOp( PropagationCallGraphBuilder builder, Graph dataflow, MethodReference op, - int shapeSrcOperand) - throws IOException { + int shapeSrcOperand) { Map reshapeTypes = getShapeSourceCalls(op, builder, shapeSrcOperand); for (PointsToSetVariable to : reshapeTypes.keySet()) { diff --git a/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/types/TensorType.java b/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/types/TensorType.java index dceb6b721..2747ae171 100644 --- a/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/types/TensorType.java +++ b/com.ibm.wala.cast.python.ml/source/com/ibm/wala/cast/python/ml/types/TensorType.java @@ -572,7 +572,7 @@ public static TensorType mnistInput() { return new TensorType(FLOAT32.name().toLowerCase(Locale.ROOT), Arrays.asList(batch, vec)); } - public static TensorType shapeArg(CGNode node, int literalVn) throws IOException { + public static TensorType shapeArg(CGNode node, int literalVn) { logger.fine(() -> node.getIR().toString()); Map> dims = new TreeMap<>(); DefUse du = node.getDU(); @@ -632,14 +632,19 @@ public static TensorType shapeArg(CGNode node, int literalVn) throws IOException ((AstMethod) node.getMethod()) .debugInfo() .getInstructionPosition(du.getDef(val).iIndex()); - System.err.println(p); - SourceBuffer b = new SourceBuffer(p); - String expr = b.toString(); - System.err.println(expr); - Integer ival = PythonInterpreter.interpretAsInt(expr); - if (ival != null) { - dims.put(index, new NumericDim(ival)); - continue; + // `SourceBuffer(Position)` reads the underlying source file. If the file + // is unavailable (synthetic / detached position), fall through to the + // symbolic-dim fallback below rather than propagating the I/O failure. + try { + SourceBuffer b = new SourceBuffer(p); + String expr = b.toString(); + Integer ival = PythonInterpreter.interpretAsInt(expr); + if (ival != null) { + dims.put(index, new NumericDim(ival)); + continue; + } + } catch (IOException e) { + logger.fine(() -> "Could not read source for shape-arg position " + p + ": " + e); } } dims.put(index, new SymbolicDim("?"));