fix: ensuring that TO_STRING conversion functions do not panic - #1903
fix: ensuring that TO_STRING conversion functions do not panic#1903Angus-Bethke-Bachmann wants to merge 10 commits into
Conversation
Build Artifacts🐧 Linux
From workflow run 🪟 Windows
From workflow run |
| * | ||
| ******************************************************************************) | ||
| VAR_GLOBAL CONSTANT | ||
| __BOOL_STRING_LENGTH : DINT := 5; |
There was a problem hiding this comment.
Not sure this will show up as you intent. The hover on IDE will probably not resolve that constant
There was a problem hiding this comment.
Good point, I switched to literals.
| assert_eq!("TRUE", terminated_str(&dest)); | ||
| unsafe { WORD_TO_STRING_EXT(u16::MAX, dest.as_mut_ptr()) }; | ||
| assert_eq!("65535", terminated_str(&dest)); | ||
| unsafe { LWORD_TO_STRING_EXT(u64::MAX, dest.as_mut_ptr()) }; |
There was a problem hiding this comment.
Unsigned tests seem to be missing
|
|
||
| unsafe { LWORD_TO_STRING_EXT(input, dest.as_mut_ptr()) }; | ||
|
|
||
| assert_eq!(input.to_string(), terminated_str(&dest)); |
| assert_eq!("-99999999999999.250000", terminated_str(&dest)); | ||
|
|
||
| unsafe { LREAL_TO_STRING_EXT(f64::NEG_INFINITY, dest.as_mut_ptr()) }; | ||
| assert_eq!("-inf", terminated_str(&dest)); |
| unsafe { REAL_TO_STRING_EXT(1.5e7, dest.as_mut_ptr()) }; | ||
| assert_eq!("1.500000e7", terminated_str(&dest)); | ||
|
|
||
| unsafe { REAL_TO_STRING_EXT(-999_999.25, dest.as_mut_ptr()) }; |
| printf('%s$N', REF(DT_TO_STRING(DT#2106-02-07-06:28:15))); // CHECK-NEXT: DT#2106-02-07-06:28:15 | ||
| printf('%s$N', REF(TOD_TO_STRING(TOD#1:2:3))); // CHECK-NEXT: TOD#01:02:03 | ||
| printf('%s$N', REF(TOD_TO_STRING(TOD#23:59:59.999))); // CHECK-NEXT: TOD#23:59:59.999 | ||
| printf('%s$N', REF(DATE_TO_STRING(-1))); // CHECK-NEXT: D#2106-02-07 |
There was a problem hiding this comment.
maybe compare with codesys here?
There was a problem hiding this comment.
It doesn't compile at all in CODESYS. We should probably consider adding some validations for date literals to mirror the functionality.
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8341c1146f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| write_terminated(dest, STRING_CAPACITY, format_args!("{input:.6}")); | ||
| } else { | ||
| write_terminated(dest, STRING_CAPACITY, format_args!("{input:.6e}")); |
There was a problem hiding this comment.
Bound writes to the actual destination capacity
When LREAL_TO_STRING_EXT receives a normal default STRING, as it does in the existing lreal_to_string_conversion test, the destination has 81 bytes, but this passes 2048 to write_terminated, which creates a 2047-byte mutable slice from that pointer. This is undefined behavior even when the formatted value is short, and a smaller permitted VAR_IN_OUT string can cause a direct buffer overflow. TL;DR: Do not assume that every caller provides a STRING[2048] buffer.
Useful? React with 👍 / 👎.
Problem: The *_TO_STRING conversions cover only a few widths, format the short date and time types without their literal prefixes, and can panic on unexpected input or overflow their result buffers. Solution: Move the TO_STRING and STRING_TO declarations into dedicated standard library files, add the missing BOOL, integer and bit-string conversions with well defined result lengths, and format date and time values with their literal prefixes through one panic-free writer. Lengths are sized for the 64-bit nanosecond types used on this release line. Backport of #1903. Refs: PRG-4692 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
0 findings in 1s for $0.00 between |
Problem: The TO_STRING writers formatted through a 2047-byte slice built over the destination pointer, so a caller that hands LREAL_TO_STRING_EXT a shorter STRING lends out memory it does not own, and the REAL, LREAL and 64-bit date and time conversions still assumed a STRING[2048] result. Solution: Format through a writer that copies at most the declared result length behind the pointer, and give the REAL, LREAL, LDT, LDATE and LTOD conversions exact result lengths in their declarations.
Problem: LDT_TO_STRING and LDATE_TO_STRING returned bare ISO text while every other date and time conversion carries the literal prefix of its type. Solution: Emit the LDT# and LDATE# prefixes and size the declared results for them.
…iteral Problem: The temporal literal test still expects unprefixed TIME, LTIME, LTOD and DT output, and the duration test spells LTIME#106752d, which overflows the 64-bit nanosecond range and is rejected at compile time since the literal grammar rework. Solution: Prefix the expected output and remove the overflowing literal; the untyped 9223372800000000000 case next to it still covers the wrapped runtime value.
1cc84d1 to
c961249
Compare
|
0 findings in 4m 32s for $0.15 between |
Added
Changed
Testing
Refs: PRG-4692