Validate sparse tensor external file paths (#28408)
## Description
Adds path traversal validation for sparse tensors with external data,
closing a gap where `SparseTensorProtoToDenseTensorProto` would read
external files without checking whether the path escapes the model
directory.
### Bug fix (pre-existing)
- **`CopySparseData` indices size check**: The `raw_data().size()` check
was wrong for external data (where `raw_data` is empty). Fixed by adding
a pre-unpack `raw_data` size guard for inline data and a post-unpack
`unpack_buffer` size check for all data sources.
### Tests
- **Security tests** (tensorutils_test.cc): Path traversal blocked
(values, indices), absolute path blocked (values, indices), zero-element
regression (zero dense elements, zero NNZ). All create escaping files
and assert specifically for `"escapes"` error.
- **Positive tests** (sparse_kernels_test.cc): 7 end-to-end tests for
legitimate sparse tensors with external data — external values, external
indices (INT64/INT32/INT16/INT8), both external (rank-1 and rank-2 COO).
### Known limitation (deferred)
ORT_MEM_ADDR in-memory external data for sparse tensors can trigger
arbitrary memory reads. This is a separate issue from path validation —
`LoadSparseInitializerOrtFormat` legitimately uses in-memory markers for
ORT-format models, so blanket rejection would break functionality.
Should be addressed in a separate PR.
## Motivation and Context
A malicious ONNX model could use `../` path traversal in sparse tensor
external data locations to read arbitrary files outside the model
directory. Dense tensors already had this validation; sparse tensors did
not.
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>