From eab5f67c5c48393c858f16a1975af773b795d2b9 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 13 Dec 2020 09:33:05 -0600 Subject: [PATCH] Fix buffer with NULL data pointer issue. Simply prevent buffers from ever having a NULL data pointer. --- src/core/buffer.c | 11 +++++------ src/core/ev.c | 46 +++++++++++++++++++++++++++++++++++++++++++- test/suite0008.janet | 8 ++++++++ 3 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/core/buffer.c b/src/core/buffer.c index 9656b13a..a1b162ff 100644 --- a/src/core/buffer.c +++ b/src/core/buffer.c @@ -31,12 +31,11 @@ /* Initialize a buffer */ JanetBuffer *janet_buffer_init(JanetBuffer *buffer, int32_t capacity) { uint8_t *data = NULL; - if (capacity > 0) { - janet_gcpressure(capacity); - data = malloc(sizeof(uint8_t) * (size_t) capacity); - if (NULL == data) { - JANET_OUT_OF_MEMORY; - } + if (capacity < 4) capacity = 4; + janet_gcpressure(capacity); + data = malloc(sizeof(uint8_t) * (size_t) capacity); + if (NULL == data) { + JANET_OUT_OF_MEMORY; } buffer->count = 0; buffer->capacity = capacity; diff --git a/src/core/ev.c b/src/core/ev.c index 8691c77b..b99e223b 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -377,12 +377,56 @@ static int janet_stream_getter(void *p, Janet key, Janet *out) { return 0; } +static void janet_stream_marshal(void *p, JanetMarshalContext *ctx) { + JanetStream *s = p; + if (!(ctx->flags & JANET_MARSHAL_UNSAFE)) { + janet_panic("can only marshal stream with unsafe flag"); + } + janet_marshal_abstract(ctx, p); + janet_marshal_int(ctx, (int32_t) s->flags); + janet_marshal_int64(ctx, (intptr_t) s->methods); +#ifdef JANET_WINDOWS + /* TODO - ref counting to avoid situation where a handle is closed or GCed + * while in transit, and it's value gets reused. DuplicateHandle does not work + * for network sockets, and in general for winsock it is better to nipt duplicate + * unless there is a need to. */ + janet_marshal_int64(ctx, (int64_t)(s->handle)); +#else + /* Marshal after dup becuse it is easier than maintaining our own ref counting. */ + int duph = dup(s->handle); + if (duph < 0) janet_panicf("failed to duplicate stream handle: %V", janet_ev_lasterr()); + janet_marshal_int(ctx, (int32_t)(duph)); +#endif +} + +static void *janet_stream_unmarshal(JanetMarshalContext *ctx) { + if (!(ctx->flags & JANET_MARSHAL_UNSAFE)) { + janet_panic("can only unmarshal stream with unsafe flag"); + } + JanetStream *p = janet_unmarshal_abstract(ctx, sizeof(JanetStream)); + /* Can't share listening state and such across threads */ + p->_mask = 0; + p->state = NULL; + p->flags = (uint32_t) janet_unmarshal_int(ctx); + p->methods = (void *) janet_unmarshal_int64(ctx); +#ifdef JANET_WINDOWS + p->handle = (JanetHandle) janet_unmarshal_int64(ctx); +#else + p->handle = (JanetHandle) janet_unmarshal_int(ctx); +#endif + return p; +} + + const JanetAbstractType janet_stream_type = { "core/stream", janet_stream_gc, janet_stream_mark, janet_stream_getter, - JANET_ATEND_GET + NULL, + janet_stream_marshal, + janet_stream_unmarshal, + JANET_ATEND_UNMARSHAL }; /* Register a fiber to resume with value */ diff --git a/test/suite0008.janet b/test/suite0008.janet index 49deaaa6..a10508bf 100644 --- a/test/suite0008.janet +++ b/test/suite0008.janet @@ -336,4 +336,12 @@ neldb\0\0\0\xD8\x05printG\x01\0\xDE\xDE\xDE'\x03\0marshal_tes/\x02 (check-replacer "aba" "ZZZZZZ" "ababababababa") (check-replacer "aba" "" "ababababababa") +# Peg bug +(assert (deep= @[] (peg/match '(any 1) @"")) "peg empty pattern 1") +(assert (deep= @[] (peg/match '(any 1) (buffer))) "peg empty pattern 2") +(assert (deep= @[] (peg/match '(any 1) "")) "peg empty pattern 3") +(assert (deep= @[] (peg/match '(any 1) (string))) "peg empty pattern 4") +(assert (deep= @[] (peg/match '(* "test" (any 1)) @"test")) "peg empty pattern 5") +(assert (deep= @[] (peg/match '(* "test" (any 1)) (buffer "test"))) "peg empty pattern 6") + (end-suite)