Fix CSE errors out on string tensor attributes#28422
Conversation
@microsoft-github-policy-service agree company="Microsoft" |
There was a problem hiding this comment.
Pull request overview
Fixes a crash in the Common Subexpression Elimination (CSE) graph optimizer when encountering scalar STRING tensor attributes (e.g., LabelEncoder’s keys_tensor) by treating those attributes as unsupported for hashing instead of enforcing.
Changes:
- Replaced an
ORT_ENFORCEon STRING tensor attributes inGetTensorAttributeHashwith an early return (hash 0) to avoid crashing during optimization. - Updated the local comment to document how STRING tensor attributes are handled.
- Fixed a lifetime bug in a test utility by avoiding a
std::string_viewbound to a temporary string returned byGetProviderOptionPrefix.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
onnxruntime/test/util/default_providers.cc |
Prevents dangling std::string_view by storing the provider option prefix as a std::string before comparing/stripping it. |
onnxruntime/core/optimizer/common_subexpression_elimination.cc |
Avoids CSE crash on scalar STRING tensor attributes by returning a neutral hash instead of enforcing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
e6ec7d4 to
8a81fb2
Compare
b7f1cc2 to
9535d7f
Compare
|
Please, do not force-push, it makes it difficult to see what changes occurred in-between the iterations. |
The CSE optimizer crashed with ORT_ENFORCE when encountering a node with a string tensor attribute (e.g., LabelEncoder with keys_tensor of type STRING). Replace the enforce with an early return of hash 0, treating such nodes as distinct (consistent with AreScalarTensorAttributeEqual). Fixes #28413 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…28413) Agent-Logs-Url: https://github.com/microsoft/onnxruntime/sessions/0ea57f90-11b2-48df-ad71-d540fdb088e2 Co-authored-by: rajatmonga <15679194+rajatmonga@users.noreply.github.com>
Use LabelEncoder (ai.onnx.ml) instead of Constant nodes so the STRING tensor attribute survives Model::Load and actually exercises GetTensorAttributeHash. Remove the .onnx test data file and generate.py additions that are no longer needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
df1e17c to
96696b8
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
onnxruntime/test/optimizer/cse_test.cc:307
- This test hard-codes the ONNX-ML domain string in multiple places (opset import and AddNode). Using the existing
kMLDomainconstant would avoid typos and keep the domain value consistent across tests.
Model model("CseStringTensorAttrTest", false, ModelMetaData(), PathString(),
IOnnxRuntimeOpSchemaRegistryList(),
{{kOnnxDomain, 21}, {"ai.onnx.ml", 4}}, {}, logger);
auto& graph = model.MainGraph();
| TEST(CseTests, StringTensorAttr) { | ||
| // Regression test for https://github.com/microsoft/onnxruntime/issues/28413. | ||
| // CSE must not crash when it encounters a node with a STRING tensor attribute. | ||
| // We use LabelEncoder (ai.onnx.ml) because it retains its STRING tensor attribute | ||
| // through Model::Load (unlike Constant nodes which are converted to initializers). | ||
| const auto& logger = DefaultLoggingManager().DefaultLogger(); | ||
| Model model("CseStringTensorAttrTest", false, ModelMetaData(), PathString(), | ||
| IOnnxRuntimeOpSchemaRegistryList(), | ||
| {{kOnnxDomain, 21}, {"ai.onnx.ml", 4}}, {}, logger); | ||
| auto& graph = model.MainGraph(); |
| TEST(CseTests, StringTensorAttr) { | ||
| // Regression test for https://github.com/microsoft/onnxruntime/issues/28413. | ||
| // CSE must not crash when it encounters a node with a STRING tensor attribute. | ||
| // We use LabelEncoder (ai.onnx.ml) because it retains its STRING tensor attribute | ||
| // through Model::Load (unlike Constant nodes which are converted to initializers). | ||
| const auto& logger = DefaultLoggingManager().DefaultLogger(); | ||
| Model model("CseStringTensorAttrTest", false, ModelMetaData(), PathString(), | ||
| IOnnxRuntimeOpSchemaRegistryList(), | ||
| {{kOnnxDomain, 21}, {"ai.onnx.ml", 4}}, {}, logger); |
|
Reverting PR as there are other issues. @Dmitri is submitting a better one. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
onnxruntime/test/optimizer/cse_test.cc:350
- This comment is now misleading: the optimizer hashes
STRINGtensor attributes andAreScalarTensorAttributeEqualcompares theirstring_data(), so string tensor attributes are not generally treated as distinct. In this specific test theLabelEncodernodes remain distinct becauseai.onnx.mlis not treated as a supported deterministic domain by CSE, not because of the string attribute handling.
// CSE won't merge these nodes (STRING tensor attrs are treated as distinct),
// but it must not crash when hashing them.
| TEST(CseTests, StringTensorAttr) { | ||
| // Regression test for https://github.com/microsoft/onnxruntime/issues/28413. | ||
| // CSE must not crash when it encounters a node with a STRING tensor attribute. | ||
| // We use LabelEncoder (ai.onnx.ml) because it retains its STRING tensor attribute | ||
| // through Model::Load (unlike Constant nodes which are converted to initializers). | ||
| const auto& logger = DefaultLoggingManager().DefaultLogger(); | ||
| Model model("CseStringTensorAttrTest", false, ModelMetaData(), PathString(), | ||
| IOnnxRuntimeOpSchemaRegistryList(), | ||
| {{kOnnxDomain, 21}, {"ai.onnx.ml", 4}}, {}, logger); |
| if (utils::HasString(lhs_t)) { | ||
| return AreRangesEqual(lhs_t.string_data(), rhs_t.string_data()); |
Description
The CSE optimizer crashed with
ORT_ENFORCEwhen encountering a node with a string tensor attribute (e.g.,LabelEncoderwithkeys_tensorof type STRING). This replaces the enforce with an early return of hash 0, treating such nodes as distinct — consistent with howAreScalarTensorAttributeEqualalready handles string tensors.Motivation and Context
Fixes #28413 — regression in 1.25.1 where models using
LabelEncoder(or any op with string tensor attributes) crash during graph optimization.Changes
ORT_ENFORCE(data_type != STRING)with an early return inGetTensorAttributeHash