lrcyyds1 opened a new issue, #20263:
URL: https://github.com/apache/tvm/issues/20263

   
   
     ### Expected behavior
   
     An ONNX `Slice` whose `starts` is a runtime input (not an initializer) 
with a negative value — e.g. `starts=[-2]` to take the last 2 elements of a 
dynamic axis, the standard GPT-2-style pattern — should
     return the last 2 elements. Negative indices are part of the ONNX Slice 
spec.
   
     ### Actual behavior
   
     Silent wrong results: the output has the correct shape but contains 
**zeros** (out-of-bounds memory that happens to be zeroed). Both official build 
pipelines (default and `get_default_pipeline`) produce the
     same wrong values.
   
     Root cause is op-level: the ONNX frontend lowers runtime (non-constant) 
`starts` to `relax.dynamic_strided_slice` **without normalizing negative 
values** (negative `axes` are normalized; `starts`/`ends` are
     passed through raw), and `dynamic_strided_slice` itself does not handle 
negative `begin` — any negative `begin`, in-range or out-of-bound, static or 
symbolic dim, produces zeros/garbage, while the same inputs
     through static `strided_slice` are correct. Negative `end` works. Constant 
`starts` take a frontend shortcut to the static op, which is why the bug only 
shows with runtime `starts`.
   
     ### Environment
   
     ```text
     OS: Linux x86_64
     Target: llvm
     TVM commit: 2a2b293c02269f4d9f3526c5b03a7548578e78e8 (current main)
     ```
   
     ### Steps to reproduce (end-to-end ONNX)
     
     ```python
     import numpy as np, onnx, tvm
     from onnx import helper, TensorProto
     from tvm import relax
     from tvm.relax.frontend.onnx import from_onnx
   
     X = helper.make_tensor_value_info('x', TensorProto.FLOAT, [8])
     S = helper.make_tensor_value_info('starts', TensorProto.INT64, [1])
     E = helper.make_tensor_value_info('ends', TensorProto.INT64, [1])
     Y = helper.make_tensor_value_info('y', TensorProto.FLOAT, [2])
     node = helper.make_node('Slice', ['x', 'starts', 'ends'], ['y'])
     graph = helper.make_graph([node], 'g', [X, S, E], [Y])
     model = helper.make_model(graph, opset_imports=[helper.make_opsetid('', 
13)])
     model.ir_version = 8
   
     mod = from_onnx(model)
     data = np.clip(np.random.RandomState(7).randn(8), -1, 1).astype("float32")
     exe = tvm.relax.build(mod, target=tvm.target.Target("llvm"), 
exec_mode="compiled")
     got = relax.VirtualMachine(exe, tvm.cpu())["main"](
         tvm.runtime.tensor(data, tvm.cpu()),
         tvm.runtime.tensor(np.array([-2], "int64"), tvm.cpu()),
         tvm.runtime.tensor(np.array([np.iinfo(np.int64).max], "int64"), 
tvm.cpu())).numpy()
     print(got)        # [0., 0.]  — expected data[-2:]
     ```
   
     Op-level isolation (no ONNX): `relax.op.dynamic_strided_slice(x, 
const([-2]), const([8]), const([1]))` on `x: (8,)` returns zeros; 
`relax.op.strided_slice(x, [0], [-2], [8], [1])` returns the correct last-2
     elements. Larger negative begins (e.g. `-58`) read garbage (`5.7e+16`) — 
out-of-bounds reads, potential segfault.
   
     Fix direction: either normalize negative `begin`/`end` (add dim, then 
clip) inside `dynamic_strided_slice`, or normalize in the ONNX frontend before 
lowering (mirroring what it already does for negative
     `axes`).
   
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to