From 11cd1279d7c132e77f6d7314ecd82b1402b72777 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 2 Dec 2018 15:29:21 -0500 Subject: [PATCH] Update Makefile and fix fiber issues. When creating an invalid fiber with the C api, the program could segfault. This protects against this kind of segafault. --- Makefile | 21 +++++++-------------- src/core/fiber.c | 36 ++++++++++++++++++++---------------- test/suite2.janet | 2 +- test/suite3.janet | 28 ++++++++++++++++++++++++++++ 4 files changed, 56 insertions(+), 31 deletions(-) create mode 100644 test/suite3.janet diff --git a/Makefile b/Makefile index c6074ff4..cdb1b548 100644 --- a/Makefile +++ b/Makefile @@ -136,6 +136,7 @@ $(JANET_EMTARGET): $(JANET_EMOBJECTS) TEST_SOURCES=$(wildcard ctest/*.c) TEST_OBJECTS=$(patsubst %.c,%.o,$(TEST_SOURCES)) TEST_PROGRAMS=$(patsubst %.c,%.out,$(TEST_SOURCES)) +TEST_SCRIPTS=$(wildcard test/suite*.janet) ctest/%.o: ctest/%.c $(JANET_HEADERS) $(CC) $(CFLAGS) -o $@ -c $< @@ -153,22 +154,14 @@ valgrind: $(JANET_TARGET) valgrind --leak-check=full -v ./$(JANET_TARGET) test: $(JANET_TARGET) $(TEST_PROGRAMS) - ctest/system_test.out - ctest/array_test.out - ctest/buffer_test.out - ctest/table_test.out - ./$(JANET_TARGET) test/suite0.janet - ./$(JANET_TARGET) test/suite1.janet - ./$(JANET_TARGET) test/suite2.janet + for f in ctest/*.out; do "$$f" || exit; done + for f in test/*.janet; do ./$(JANET_TARGET) "$$f" || exit; done + +VALGRIND_COMMAND=valgrind --leak-check=full -v valtest: $(JANET_TARGET) $(TEST_PROGRAMS) - valgrind --leak-check=full -v ctest/system_test.out - valgrind --leak-check=full -v ctest/array_test.out - valgrind --leak-check=full -v ctest/buffer_test.out - valgrind --leak-check=full -v ctest/table_test.out - valgrind --leak-check=full -v ./$(JANET_TARGET) test/suite0.janet - valgrind --leak-check=full -v ./$(JANET_TARGET) test/suite1.janet - valgrind --leak-check=full -v ./$(JANET_TARGET) test/suite2.janet + for f in ctest/*.out; do $(VALGRIND_COMMAND) "$$f" || exit; done + for f in test/*.janet; do $(VALGRIND_COMMAND) ./$(JANET_TARGET) "$$f" || exit; done ################### ##### Natives ##### diff --git a/src/core/fiber.c b/src/core/fiber.c index 00049a9c..7f806c0c 100644 --- a/src/core/fiber.c +++ b/src/core/fiber.c @@ -50,7 +50,8 @@ static JanetFiber *make_fiber(int32_t capacity) { /* Initialize a new fiber */ JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity) { JanetFiber *fiber = make_fiber(capacity); - janet_fiber_funcframe(fiber, callee); + if (janet_fiber_funcframe(fiber, callee)) + janet_fiber_set_status(fiber, JANET_STATUS_ERROR); return fiber; } @@ -64,7 +65,8 @@ JanetFiber *janet_fiber_n(JanetFunction *callee, int32_t capacity, const Janet * } memcpy(fiber->data + fiber->stacktop, argv, argn * sizeof(Janet)); fiber->stacktop = newstacktop; - janet_fiber_funcframe(fiber, callee); + if (janet_fiber_funcframe(fiber, callee)) + janet_fiber_set_status(fiber, JANET_STATUS_ERROR); return fiber; } @@ -128,13 +130,7 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) { int32_t oldframe = fiber->frame; int32_t nextframe = fiber->stackstart; int32_t nextstacktop = nextframe + func->def->slotcount + JANET_FRAME_SIZE; - - /* Check strict arity */ - if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) { - if (func->def->arity != (fiber->stacktop - fiber->stackstart)) { - return 1; - } - } + int32_t next_arity = fiber->stacktop - fiber->stackstart; if (fiber->capacity < nextstacktop) { janet_fiber_setcapacity(fiber, 2 * nextstacktop); @@ -167,6 +163,13 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) { } } + /* Check strict arity AFTER getting fiber to valid state. */ + if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) { + if (func->def->arity != next_arity) { + return 1; + } + } + /* Good return */ return 0; } @@ -192,15 +195,9 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) { int32_t i; int32_t nextframetop = fiber->frame + func->def->slotcount; int32_t nextstacktop = nextframetop + JANET_FRAME_SIZE; + int32_t next_arity = fiber->stacktop - fiber->stackstart; int32_t stacksize; - /* Check strict arity */ - if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) { - if (func->def->arity != (fiber->stacktop - fiber->stackstart)) { - return 1; - } - } - if (fiber->capacity < nextstacktop) { janet_fiber_setcapacity(fiber, 2 * nextstacktop); } @@ -244,6 +241,13 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) { janet_fiber_frame(fiber)->pc = func->def->bytecode; janet_fiber_frame(fiber)->flags |= JANET_STACKFRAME_TAILCALL; + /* Check strict arity AFTER getting fiber to valid state. */ + if (func->def->flags & JANET_FUNCDEF_FLAG_FIXARITY) { + if (func->def->arity != next_arity) { + return 1; + } + } + /* Good return */ return 0; } diff --git a/test/suite2.janet b/test/suite2.janet index 5b639f86..7836e000 100644 --- a/test/suite2.janet +++ b/test/suite2.janet @@ -40,7 +40,7 @@ (assert (= (length @"abcdef") 6) "buffer length") # Looping idea -(def xs +(def xs (seq [x :in '[-1 0 1] y :in '[-1 0 1] :when (not= x y 0)] (tuple x y))) (def txs (apply tuple xs)) diff --git a/test/suite3.janet b/test/suite3.janet new file mode 100644 index 00000000..bd5236fc --- /dev/null +++ b/test/suite3.janet @@ -0,0 +1,28 @@ +# Copyright (c) 2018 Calvin Rose +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +(import test/helper :prefix "" :exit true) +(start-suite 3) + +(assert (= (length (range 10)) 10) "(range 10)") +(assert (= (length (range 1 10)) 9) "(range 1 10)") +(assert (deep= @{:a 1 :b 2 :c 3} (zipcoll '[:a :b :c] '[1 2 3])) "zipcoll") + +(end-suite)