You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The itk::StringTo* helpers in Modules/Core/Common/src/itkStringConvert.cxx accept a valid numeric prefix followed by arbitrary trailing content. itk::StringToDouble("1.25junk", ctx) returns 1.25 rather than throwing, because the validity check is "did the conversion start" (end == begin) rather than "did the conversion consume the input".
Every IO call site migrated to these helpers in #6089 inherits that leniency, so a malformed header field or DICOM Decimal String can silently yield a plausible-looking value instead of a parse error.
Current behavior
Measured against ITKCommon (macOS arm64), alongside the std::stod these helpers replaced:
Input
itk::StringToDouble
std::stod
"1.25junk"
1.25
1.25
"1.25 "
1.25
1.25
" 1.25"
1.25
1.25
"1.25\2.5"
1.25
1.25
"junk"
throws
throws
"1.25"
1.25
1.25
The behavior is identical to std::stod, so it long predates the locale work in #6695; it is inherited, not introduced. strtod's endptr contract distinguishes "nothing consumed" from "something consumed" and leaves "partially consumed" to the caller, and std::stod chose the lenient reading.
Why this is not a one-line fix
A naive *end != '\0' rejection would break valid input:
DICOM DS explicitly permits leading and trailing spaces, so "1.25 " must keep parsing. Any strict check has to skip trailing whitespace before rejecting.
itk::StringToDouble / StringToFloat are now the shared funnel for many readers (NRRD, DICOM, and others migrated in BUG: Wrap std::sto* exceptions in IO with itk::ExceptionObject (#3213) #6089). Tightening validation is an input-compatibility change: files that load today could start failing, which is a deliberate decision rather than a drive-by fix.
Proposal
Reject trailing content that is not whitespace, for the whole itk::StringTo* family (integer helpers included — std::stoll/std::stoull are lenient the same way).
Keep leading and trailing whitespace valid.
Add GTest coverage for the prefix cases: "1.25junk", "1.25\2.5", "1 2", "0x10", and the whitespace cases that must still pass.
Survey call sites for readers that legitimately hand these helpers a substring with a delimiter still attached, and fix those to split first rather than relying on the lenient parse.
Provenance
Raised as a P1 by an automated reviewer on #6695 (discussion_r3646959273), attributed there to that PR's strtod_l change. Verification against the merge base showed the behavior unchanged from std::stod, so it was kept out of #6695's scope and tracked here instead.
The
itk::StringTo*helpers inModules/Core/Common/src/itkStringConvert.cxxaccept a valid numeric prefix followed by arbitrary trailing content.itk::StringToDouble("1.25junk", ctx)returns1.25rather than throwing, because the validity check is "did the conversion start" (end == begin) rather than "did the conversion consume the input".Every IO call site migrated to these helpers in #6089 inherits that leniency, so a malformed header field or DICOM Decimal String can silently yield a plausible-looking value instead of a parse error.
Current behavior
Measured against
ITKCommon(macOS arm64), alongside thestd::stodthese helpers replaced:itk::StringToDoublestd::stod"1.25junk"1.251.25"1.25 "1.251.25" 1.25"1.251.25"1.25\2.5"1.251.25"junk""1.25"1.251.25The behavior is identical to
std::stod, so it long predates the locale work in #6695; it is inherited, not introduced.strtod'sendptrcontract distinguishes "nothing consumed" from "something consumed" and leaves "partially consumed" to the caller, andstd::stodchose the lenient reading.Why this is not a one-line fix
A naive
*end != '\0'rejection would break valid input:"1.25 "must keep parsing. Any strict check has to skip trailing whitespace before rejecting.itk::StringToDouble/StringToFloatare now the shared funnel for many readers (NRRD, DICOM, and others migrated in BUG: Wrap std::sto* exceptions in IO with itk::ExceptionObject (#3213) #6089). Tightening validation is an input-compatibility change: files that load today could start failing, which is a deliberate decision rather than a drive-by fix.Proposal
itk::StringTo*family (integer helpers included —std::stoll/std::stoullare lenient the same way)."1.25junk","1.25\2.5","1 2","0x10", and the whitespace cases that must still pass.Provenance
Raised as a P1 by an automated reviewer on #6695 (
discussion_r3646959273), attributed there to that PR'sstrtod_lchange. Verification against the merge base showed the behavior unchanged fromstd::stod, so it was kept out of #6695's scope and tracked here instead.