fix: guard against uint32 underflow in memset/memcpy and strings unit

When size=0 was passed to memset() or memcpy(), the loop bound
`0 to size-1` underflowed to $FFFFFFFF, iterating ~4 billion times
and causing an immediate page fault.

Added `if size = 0 then exit` guards to both memset() and memcpy()
in util.pas.

Also guarded all `for i:=0 to X-1` loops in strings.pas where X
could be 0 on empty string inputs:
- stringToUpper: wrap loop in `if stringSize > 0`
- stringToLower: wrap loop in `if stringSize > 0`
- stringEquals: early exit when both sizes are 0
- stringToInt: early exit when string is empty

Additionally fixed all previously identified bugs in strings.pas:
- hexStringToInt: guard against empty string underflow
- stringConcat: cache stringSize calls to avoid redundant O(n) scans
- stringTrim: clamp length to source string size
- stringSub: bounds check start/size against source length
- stringReplace: complete rewrite - was using stringEquals() for
  substring matching (only matched at string end), dropped prefix
  chars, had dangling assignment overwriting valid result with
  uninitialized pointer, and had unused variable
- stringIndexOf: rewritten to use new stringMatchAt() helper for
  correct substring matching
- stringContains: simplified to delegate to fixed stringIndexOf(),
  also fixing uint32 underflow when sub was empty
- stringToInt: removed always-true `v >= 0` check on uint32
- intToString: implemented (was a stub returning ' ')
- Added stringMatchAt() helper for prefix comparison
- Added comprehensive UnitTest procedure with 77 assertions
  including adversarial empty/nil/boundary inputs
This commit is contained in:
t3hn3rd committed 2026-03-01 02:33:28 +00:00
1 parent 084130da80
commit beb4b253ab
3 files changed
+399 -106

No files matched your search

+394 -106
View File
File diff suppressed because it is too large. Load diff
+2
View File
@@ -414,6 +414,7 @@ var
begin begin
//push_trace('util.memset'); //push_trace('util.memset');
if size = 0 then exit;
for i:=0 to size-1 do begin for i:=0 to size-1 do begin
loc:= puint8(location + i); loc:= puint8(location + i);
loc^:= value; loc^:= value;
@@ -428,6 +429,7 @@ var
begin begin
//push_trace('util.memcpy'); //push_trace('util.memcpy');
if size = 0 then exit;
for i:=0 to size-1 do begin for i:=0 to size-1 do begin
src:= puint8(source + i); src:= puint8(source + i);
dst:= puint8(dest + i); dst:= puint8(dest + i);
+3
View File
@@ -251,6 +251,9 @@ begin
{ Initialize visual terminal (registers with desktop search) } { Initialize visual terminal (registers with desktop search) }
vterminal.init; vterminal.init;
{ Run unit tests }
strings.UnitTest;
{ Main render loop } { Main render loop }
syslog.logln('KERNEL', 'Entering main render loop.'); syslog.logln('KERNEL', 'Entering main render loop.');
tracer.push_trace('kmain.MAINLOOP'); tracer.push_trace('kmain.MAINLOOP');