Fix QA findings: FRE GC safety, WAIT mask=0, ENVIRON leak, sentinel collision
- FRE(): remove strpool_gc() call during expression evaluation — temporaries on the C stack would become dangling pointers after compaction - WAIT: reject mask=0 (would infinite-loop since AND 0 is always 0) - ENVIRON: use setenv()+free() instead of putenv() to avoid memory leak and dangling pointer if pool is compacted - portio: add bounds check to com1_inp() (com1_out already had one) - kernel: use CHR$(1) sentinel prefix to avoid collision with user output - kernel: fix INPUT prompt rfind() edge case when no newline in buffer - eval.c: enlarge DATE$ format buffer to silence -Wformat-truncation
This commit is contained in:
@@ -34,8 +34,8 @@ from ipykernel.kernelbase import Kernel
|
||||
|
||||
from . import __version__
|
||||
|
||||
_SENTINEL = '<<<GWDONE>>>'
|
||||
_SENTINEL_CMD = f'PRINT "{_SENTINEL}"\n'
|
||||
_SENTINEL = '\x01GWDONE\x01'
|
||||
_SENTINEL_CMD = 'PRINT CHR$(1)+"GWDONE"+CHR$(1)\n'
|
||||
|
||||
_ERROR_RE = re.compile(
|
||||
r'(?:Syntax error|Illegal function call|Type mismatch|Out of |'
|
||||
@@ -378,13 +378,14 @@ class GWBasicKernel(Kernel):
|
||||
return before, 'done'
|
||||
|
||||
# Check for INPUT prompt: "? " at end of buffer (no newline after)
|
||||
if allow_stdin and buf.endswith(b'? ') and b'\n' not in buf[buf.rfind(b'\n') + 1:]:
|
||||
# Extract text before the "? " to show as prompt
|
||||
if allow_stdin and buf.endswith(b'? '):
|
||||
last_nl = buf.rfind(b'\n')
|
||||
prompt_line = buf[last_nl + 1:].decode('utf-8', errors='replace')
|
||||
reply = self.raw_input(prompt_line)
|
||||
self._proc.stdin.write((reply + '\n').encode())
|
||||
self._proc.stdin.flush()
|
||||
tail = buf[last_nl + 1:] if last_nl >= 0 else buf
|
||||
if b'\n' not in tail[:-2]: # no embedded newline before "? "
|
||||
prompt_line = tail.decode('utf-8', errors='replace')
|
||||
reply = self.raw_input(prompt_line)
|
||||
self._proc.stdin.write((reply + '\n').encode())
|
||||
self._proc.stdin.flush()
|
||||
|
||||
def _split_sixel(self, raw):
|
||||
"""Split raw output into (text_parts, sixel_blobs) interleaved."""
|
||||
|
||||
+4
-5
@@ -641,10 +641,9 @@ static gw_value_t eval_function(uint8_t prefix, uint8_t func_tok)
|
||||
gw_expect('(');
|
||||
arg = gw_eval(); /* can be string or numeric */
|
||||
gw_expect_rparen();
|
||||
if (arg.type == VT_STR) {
|
||||
gw_str_free(&arg.sval);
|
||||
strpool_gc();
|
||||
}
|
||||
if (arg.type == VT_STR) gw_str_free(&arg.sval);
|
||||
/* No GC here — unsafe during expression eval (temps on C stack).
|
||||
* The run loop compacts at statement boundaries instead. */
|
||||
v.type = VT_SNG;
|
||||
v.fval = (float)strpool_free();
|
||||
return v;
|
||||
@@ -996,7 +995,7 @@ static gw_value_t eval_atom(void)
|
||||
gw_chrget();
|
||||
gw_value_t v;
|
||||
v.type = VT_STR;
|
||||
char tbuf[16];
|
||||
char tbuf[40];
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm = localtime(&now);
|
||||
if (xtok == XSTMT_DATE) {
|
||||
|
||||
+7
-2
@@ -1377,7 +1377,12 @@ void gw_exec_stmt(void)
|
||||
gw_value_t val = gw_eval_str();
|
||||
char *s = gw_str_to_cstr(&val.sval);
|
||||
gw_str_free(&val.sval);
|
||||
putenv(s); /* s is intentionally not freed — putenv requires it */
|
||||
char *eq = strchr(s, '=');
|
||||
if (eq) {
|
||||
*eq = '\0';
|
||||
setenv(s, eq + 1, 1);
|
||||
}
|
||||
free(s);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2617,7 +2622,7 @@ void gw_exec_stmt(void)
|
||||
gw_skip_spaces();
|
||||
gw_expect(',');
|
||||
int mask = gw_eval_int();
|
||||
if (mask < 0 || mask > 255) gw_error(ERR_FC);
|
||||
if (mask < 0 || mask > 255 || mask == 0) gw_error(ERR_FC);
|
||||
int xor_mask = 0;
|
||||
gw_skip_spaces();
|
||||
if (gw_chrgot() == ',') {
|
||||
|
||||
+3
-1
@@ -122,7 +122,9 @@ static uint8_t com1_inp(uint16_t port)
|
||||
int reg = port - 0x3F8;
|
||||
if (reg == 5) /* LSR: transmitter ready */
|
||||
return 0x60;
|
||||
return com1_regs[reg];
|
||||
if (reg >= 0 && reg < 7)
|
||||
return com1_regs[reg];
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
static void com1_out(uint16_t port, uint8_t value)
|
||||
|
||||
Reference in New Issue
Block a user