1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-30 20:09:54 +00:00

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.
This commit is contained in:
Calvin Rose 2018-12-02 15:29:21 -05:00
parent 0469bdb06c
commit 11cd1279d7
4 changed files with 56 additions and 31 deletions

View File

@ -136,6 +136,7 @@ $(JANET_EMTARGET): $(JANET_EMOBJECTS)
TEST_SOURCES=$(wildcard ctest/*.c) TEST_SOURCES=$(wildcard ctest/*.c)
TEST_OBJECTS=$(patsubst %.c,%.o,$(TEST_SOURCES)) TEST_OBJECTS=$(patsubst %.c,%.o,$(TEST_SOURCES))
TEST_PROGRAMS=$(patsubst %.c,%.out,$(TEST_SOURCES)) TEST_PROGRAMS=$(patsubst %.c,%.out,$(TEST_SOURCES))
TEST_SCRIPTS=$(wildcard test/suite*.janet)
ctest/%.o: ctest/%.c $(JANET_HEADERS) ctest/%.o: ctest/%.c $(JANET_HEADERS)
$(CC) $(CFLAGS) -o $@ -c $< $(CC) $(CFLAGS) -o $@ -c $<
@ -153,22 +154,14 @@ valgrind: $(JANET_TARGET)
valgrind --leak-check=full -v ./$(JANET_TARGET) valgrind --leak-check=full -v ./$(JANET_TARGET)
test: $(JANET_TARGET) $(TEST_PROGRAMS) test: $(JANET_TARGET) $(TEST_PROGRAMS)
ctest/system_test.out for f in ctest/*.out; do "$$f" || exit; done
ctest/array_test.out for f in test/*.janet; do ./$(JANET_TARGET) "$$f" || exit; done
ctest/buffer_test.out
ctest/table_test.out VALGRIND_COMMAND=valgrind --leak-check=full -v
./$(JANET_TARGET) test/suite0.janet
./$(JANET_TARGET) test/suite1.janet
./$(JANET_TARGET) test/suite2.janet
valtest: $(JANET_TARGET) $(TEST_PROGRAMS) valtest: $(JANET_TARGET) $(TEST_PROGRAMS)
valgrind --leak-check=full -v ctest/system_test.out for f in ctest/*.out; do $(VALGRIND_COMMAND) "$$f" || exit; done
valgrind --leak-check=full -v ctest/array_test.out for f in test/*.janet; do $(VALGRIND_COMMAND) ./$(JANET_TARGET) "$$f" || exit; done
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
################### ###################
##### Natives ##### ##### Natives #####

View File

@ -50,7 +50,8 @@ static JanetFiber *make_fiber(int32_t capacity) {
/* Initialize a new fiber */ /* Initialize a new fiber */
JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity) { JanetFiber *janet_fiber(JanetFunction *callee, int32_t capacity) {
JanetFiber *fiber = make_fiber(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; 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)); memcpy(fiber->data + fiber->stacktop, argv, argn * sizeof(Janet));
fiber->stacktop = newstacktop; fiber->stacktop = newstacktop;
janet_fiber_funcframe(fiber, callee); if (janet_fiber_funcframe(fiber, callee))
janet_fiber_set_status(fiber, JANET_STATUS_ERROR);
return fiber; return fiber;
} }
@ -128,13 +130,7 @@ int janet_fiber_funcframe(JanetFiber *fiber, JanetFunction *func) {
int32_t oldframe = fiber->frame; int32_t oldframe = fiber->frame;
int32_t nextframe = fiber->stackstart; int32_t nextframe = fiber->stackstart;
int32_t nextstacktop = nextframe + func->def->slotcount + JANET_FRAME_SIZE; int32_t nextstacktop = nextframe + func->def->slotcount + JANET_FRAME_SIZE;
int32_t next_arity = fiber->stacktop - fiber->stackstart;
/* 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) { if (fiber->capacity < nextstacktop) {
janet_fiber_setcapacity(fiber, 2 * 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 */ /* Good return */
return 0; return 0;
} }
@ -192,15 +195,9 @@ int janet_fiber_funcframe_tail(JanetFiber *fiber, JanetFunction *func) {
int32_t i; int32_t i;
int32_t nextframetop = fiber->frame + func->def->slotcount; int32_t nextframetop = fiber->frame + func->def->slotcount;
int32_t nextstacktop = nextframetop + JANET_FRAME_SIZE; int32_t nextstacktop = nextframetop + JANET_FRAME_SIZE;
int32_t next_arity = fiber->stacktop - fiber->stackstart;
int32_t stacksize; 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) { if (fiber->capacity < nextstacktop) {
janet_fiber_setcapacity(fiber, 2 * 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)->pc = func->def->bytecode;
janet_fiber_frame(fiber)->flags |= JANET_STACKFRAME_TAILCALL; 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 */ /* Good return */
return 0; return 0;
} }

View File

@ -40,7 +40,7 @@
(assert (= (length @"abcdef") 6) "buffer length") (assert (= (length @"abcdef") 6) "buffer length")
# Looping idea # 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))) (seq [x :in '[-1 0 1] y :in '[-1 0 1] :when (not= x y 0)] (tuple x y)))
(def txs (apply tuple xs)) (def txs (apply tuple xs))

28
test/suite3.janet Normal file
View File

@ -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)