Conversation
SyWinCmd read the answer '@A<len>+<data>' of a window handler into a static buffer of 8000 bytes, which a longer answer overflowed. An answer arriving in several read() calls was corrupted, as the read loop did not advance its destination, and a failed read or an end of file made it spin. The un-escaping pass counted the two bytes of an escape as one and so ran past the end of the answer. SyWinCmd now reads exactly <len> bytes into a string object, retrying on EINTR and EAGAIN, and un-escapes them in place. FuncWindowCmd checks bounds while parsing: a string entry exceeding the answer, a number not fitting a small integer and an unknown entry raise an error. The answer is consumed before it is parsed, so these errors leave the input in sync. In package mode the answer is read from stdin, where GAP does not read ahead, so a testspecial test can put it on the line after the call. For this run_gap.sh passes on the GAP options a test asks for in a first line '#GAPOPTS <options>'. The answers carry several interdependent lengths, hence the tests are generated by dev/make-window-cmd-tests.g. This is based on the analysis and a first fix by Russ Woodroofe. Co-authored-by: Russ Woodroofe <rsw9@cornell.edu> Assisted-by: Claude Code (Fable 5.1)
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #6584 +/- ##
==========================================
+ Coverage 79.03% 79.62% +0.58%
==========================================
Files 683 683
Lines 295287 307167 +11880
Branches 8642 9519 +877
==========================================
+ Hits 233375 244574 +11199
- Misses 60096 60685 +589
- Partials 1816 1908 +92 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
I looked through your code. If I understand right, a main difference with what I had is that you read the response directly into a GAP string object, and unescape it there. That probably is a little better design. I didn't look in super detail, but the design is sound, and it is easier to compare with prior version. I'm not an expert on GAP memory management, so my check on that is not reliable. Testing: I applied the patch to a 4.16.1 tree and ran with Gap.app, both upcoming 0.8 release and also 0.7a. I didn't see any trouble with either, including with long answers to WcDialog. I will try to use this as my daily driver, and will report issues if I see anything. Sorry to take a day or so to get back here. |
|
One other comment: the test framework that is here may tend to mostly obsolete the package mode testing framework that I contributed to xgap some time ago. |
WindowCmd corrupting long answers or ones containing @xgap and GAP.app (WindowCmd corrupting long answers or ones containing @)
SyWinCmdread the answer@a<len>+<data>of a window handler into a static buffer of 8000 bytes, which a longer answer overflowed. An answer arriving in severalread()calls was corrupted, as the read loop did not advance its destination, and a failed read or an end of file made it spin. The un-escaping pass counted the two bytes of an escape as one and so ran past the end of the answer.SyWinCmdnow reads exactlylenbytes into a string object, retrying on EINTR and EAGAIN, and un-escapes them in place.FuncWindowCmdchecks bounds while parsing: a string entry exceeding the answer, a number not fitting a small integer and an unknown entry raise an error. The answer is consumed before it is parsed, so these errors leave the input in sync.In package mode the answer is read from stdin, where GAP does not read ahead, so a testspecial test can put it on the line after the call. For this
run_gap.shpasses on the GAP options a test asks for in a first line#GAPOPTS <options>. The answers carry several interdependent lengths, hence the tests are generated by dev/make-window-cmd-tests.g.This is based on the analysis and a first fix by @RussWoodroofe.
Assisted-by: Claude Code (Fable 5.1)
Alternative to and hence closes #6483. Tested with
xgap; that also lead to gap-packages/xgap#38. Not tested via GAP.app mainly because I don't know how (and its SourceForget git repository was last updated 2022?)The main motivation for this PR was a desire to have a somewhat simpler kernel implementation, and also a tighter test rig.