Compare commits

...

4 Commits

Author SHA1 Message Date
Steve Chen
99674dfeac
Merge c18322444e7d046e1e97da3763201e45a472ab93 into d527b4dbc97235986f32accf34b246ec1a758dc2 2026-06-17 09:36:21 +00:00
Steve
c18322444e fix lexer EOF OOB read and list.sort comparator signature 2026-06-17 05:36:09 -04:00
Steve
db8d52cab0 fix round trip check 2026-06-17 04:36:29 -04:00
blueloveTH
d527b4dbc9 fix msgpack 2026-06-17 16:30:17 +08:00
5 changed files with 47 additions and 14 deletions

View File

@ -56,8 +56,10 @@ static bool mpack_to_py(mpack_node_t node) {
for(size_t i = 0; i < count; i++) {
mpack_node_t key_node = mpack_node_map_key_at(node, i);
mpack_node_t val_node = mpack_node_map_value_at(node, i);
if(mpack_node_type(key_node) != mpack_type_str) {
return TypeError("msgpack: key must be strings");
mpack_type_t key_type = mpack_node_type(key_node);
if(key_type != mpack_type_str && key_type != mpack_type_int &&
key_type != mpack_type_uint) {
return TypeError("msgpack: key must be string or integer");
}
if(!mpack_to_py(key_node)) return false;
if(!mpack_to_py(val_node)) return false;
@ -101,9 +103,14 @@ static bool py_to_mpack(py_Ref object, mpack_writer_t* writer);
static bool mpack_write_dict_kv(py_Ref k, py_Ref v, void* ctx) {
mpack_writer_t* writer = ctx;
if(k->type != tp_str) return TypeError("msgpack: key must be strings");
c11_sv sv = py_tosv(k);
mpack_write_str(writer, sv.data, (size_t)sv.size);
if(k->type == tp_str) {
c11_sv sv = py_tosv(k);
mpack_write_str(writer, sv.data, (size_t)sv.size);
} else if(k->type == tp_int) {
mpack_write_int(writer, py_toint(k));
} else {
return TypeError("msgpack: key must be string or integer");
}
bool ok = py_to_mpack(v, writer);
if(!ok) mpack_write_nil(writer);
return ok;
@ -160,7 +167,10 @@ static bool msgpack_dumps(int argc, py_Ref argv) {
mpack_writer_init_growable(&writer, &data, &size);
bool ok = py_to_mpack(argv, &writer);
if(mpack_writer_destroy(&writer) != mpack_ok) { assert(false); }
if(!ok) return false;
if(!ok) {
MPACK_FREE(data);
return false;
}
assert(size <= INT32_MAX);
unsigned char* byte_data = py_newbytes(py_retval(), (int)size);
memcpy(byte_data, data, size);

View File

@ -7,6 +7,7 @@
#include <stdarg.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void c11_sbuf__ctor(c11_sbuf* self) {
@ -53,11 +54,14 @@ void c11_sbuf__write_f64(c11_sbuf* self, double val, int precision) {
char b[32];
int size;
if(precision < 0) {
size = snprintf(b, sizeof(b), "%.17g", val);
size = snprintf(b, sizeof(b), "%.*g", 15, val);
if(strtod(b, NULL) != val) {
size = snprintf(b, sizeof(b), "%.*g", 17, val);
}
c11_sbuf__write_cstr(self, b);
bool all_is_digit = true;
for(int i = 1; i < size; i++) {
if(!isdigit((unsigned char)b[i])) {
if(!isdigit(b[i])) {
all_is_digit = false;
break;
}

View File

@ -37,16 +37,24 @@ static void Lexer__dtor(Lexer* self) {
c11_vector__dtor(&self->indents);
}
static const char* lexer_source_end(Lexer* self) {
return self->src->source->data + self->src->source->size;
}
static char eatchar(Lexer* self) {
const char* end = lexer_source_end(self);
if(self->curr_char > end) return '\0';
char c = *self->curr_char;
assert(c != '\n'); // eatchar() cannot consume a newline
self->curr_char++;
self->curr_char = (self->curr_char < end) ? self->curr_char + 1 : end + 1;
return c;
}
static char eatchar_include_newline(Lexer* self) {
const char* end = lexer_source_end(self);
if(self->curr_char > end) return '\0';
char c = *self->curr_char;
self->curr_char++;
self->curr_char = (self->curr_char < end) ? self->curr_char + 1 : end + 1;
if(c == '\n') {
self->current_line++;
c11_vector__push(const char*, &self->src->line_starts, self->curr_char);
@ -189,7 +197,8 @@ static Error* LexerError(Lexer* self, const char* fmt, ...) {
err->src = self->src;
PK_INCREF(self->src);
err->lineno = self->current_line;
if(*self->curr_char == '\n') { err->lineno--; }
const char* end = lexer_source_end(self);
if(self->curr_char <= end && *self->curr_char == '\n') { err->lineno--; }
va_list args;
va_start(args, fmt);
vsnprintf(err->msg, sizeof(err->msg), fmt, args);

View File

@ -384,7 +384,10 @@ static bool list_insert(int argc, py_Ref argv) {
return true;
}
static int lt_with_key(py_TValue* a, py_TValue* b, py_TValue* key) {
static int lt_with_key(const void* a_, const void* b_, void* extra) {
py_TValue* a = (py_TValue*)a_;
py_TValue* b = (py_TValue*)b_;
py_TValue* key = (py_TValue*)extra;
if(!key) return py_less(a, b);
VM* vm = pk_current_vm;
// project a
@ -416,7 +419,7 @@ static bool list_sort(int argc, py_Ref argv) {
bool ok = c11__stable_sort(self->data,
self->length,
sizeof(py_TValue),
(int (*)(const void*, const void*, void*))lt_with_key,
lt_with_key,
key);
if(!ok) return false;

View File

@ -75,4 +75,11 @@ assert res == [42, 42]
assert x == 33
# test removing trailing newlines
assert eval('[1, 2, 3]\n \n') == [1, 2, 3]
assert eval('[1, 2, 3]\n \n') == [1, 2, 3]
# lexer doesn't read past NUL on error at end of input
try:
eval('"\\x4')
exit(1)
except SyntaxError:
pass