1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-25 06:33:16 +00:00

Address some issues found in lgtm

Caught a few potentially issues with overflows, as well as use of
unsafe function localtime.
This commit is contained in:
Calvin Rose 2019-10-10 22:59:43 -05:00
parent 8ee54e887f
commit a18a251d16
7 changed files with 122 additions and 98 deletions

View File

@ -1668,7 +1668,8 @@
:on-compile-error - callback when compilation fails - default is bad-compile\n\t :on-compile-error - callback when compilation fails - default is bad-compile\n\t
:compile-only - only compile the source, do not execute it - default is false\n\t :compile-only - only compile the source, do not execute it - default is false\n\t
:on-status - callback when a value is evaluated - default is debug/stacktrace\n\t :on-status - callback when a value is evaluated - default is debug/stacktrace\n\t
:fiber-flags - what flags to wrap the compilation fiber with. Default is :ia." :fiber-flags - what flags to wrap the compilation fiber with. Default is :ia.\n\t
:expander - an optional function that is called on each top level form before being compiled."
[opts] [opts]
(def {:env env (def {:env env
@ -1678,7 +1679,8 @@
:on-parse-error on-parse-error :on-parse-error on-parse-error
:fiber-flags guard :fiber-flags guard
:compile-only compile-only :compile-only compile-only
:source where} opts) :source where
:expander expand} opts)
(default env (fiber/getenv (fiber/current))) (default env (fiber/getenv (fiber/current)))
(default chunks (fn [buf p] (getline "" buf))) (default chunks (fn [buf p] (getline "" buf)))
(default compile-only false) (default compile-only false)
@ -1695,6 +1697,7 @@
# Evaluate 1 source form in a protected manner # Evaluate 1 source form in a protected manner
(defn eval1 [source] (defn eval1 [source]
(def source (if expand (expand source) source))
(var good true) (var good true)
(def f (def f
(fiber/new (fiber/new
@ -1718,6 +1721,7 @@
# Loop # Loop
(def buf @"") (def buf @"")
(while going (while going
(if (env :exit) (break))
(buffer/clear buf) (buffer/clear buf)
(chunks buf p) (chunks buf p)
(var pindex 0) (var pindex 0)
@ -1740,6 +1744,13 @@
env) env)
(defn quit
"Tries to exit from the current repl or context. Does not always exit the application.
Works by setting the :exit dynamic binding to true."
[]
(setdyn :exit true)
"Bye!")
(defn eval-string (defn eval-string
"Evaluates a string in the current environment. If more control over the "Evaluates a string in the current environment. If more control over the
environment is needed, use run-context." environment is needed, use run-context."
@ -2005,7 +2016,7 @@
(debug/stacktrace f x) (debug/stacktrace f x)
(print ``` (print ```
entering debugger - Ctrl-D to exit entering debugger - (quit) or Ctrl-D to exit
_fiber is bound to the suspended fiber _fiber is bound to the suspended fiber
```) ```)

View File

@ -64,7 +64,7 @@ void janet_array_ensure(JanetArray *array, int32_t capacity, int32_t growth) {
Janet *newData; Janet *newData;
Janet *old = array->data; Janet *old = array->data;
if (capacity <= array->capacity) return; if (capacity <= array->capacity) return;
int64_t new_capacity = capacity * growth; int64_t new_capacity = ((int64_t) capacity) * growth;
if (new_capacity > INT32_MAX) new_capacity = INT32_MAX; if (new_capacity > INT32_MAX) new_capacity = INT32_MAX;
capacity = (int32_t) new_capacity; capacity = (int32_t) new_capacity;
newData = realloc(old, capacity * sizeof(Janet)); newData = realloc(old, capacity * sizeof(Janet));

View File

@ -59,7 +59,7 @@ void janet_buffer_ensure(JanetBuffer *buffer, int32_t capacity, int32_t growth)
uint8_t *new_data; uint8_t *new_data;
uint8_t *old = buffer->data; uint8_t *old = buffer->data;
if (capacity <= buffer->capacity) return; if (capacity <= buffer->capacity) return;
int64_t big_capacity = capacity * growth; int64_t big_capacity = ((int64_t) capacity) * growth;
capacity = big_capacity > INT32_MAX ? INT32_MAX : (int32_t) big_capacity; capacity = big_capacity > INT32_MAX ? INT32_MAX : (int32_t) big_capacity;
janet_vm_next_collection += capacity - buffer->capacity; janet_vm_next_collection += capacity - buffer->capacity;
new_data = realloc(old, capacity * sizeof(uint8_t)); new_data = realloc(old, capacity * sizeof(uint8_t));

View File

@ -477,13 +477,19 @@ static Janet os_date(int32_t argc, Janet *argv) {
janet_arity(argc, 0, 1); janet_arity(argc, 0, 1);
(void) argv; (void) argv;
time_t t; time_t t;
struct tm t_infos;
struct tm *t_info; struct tm *t_info;
if (argc) { if (argc) {
t = (time_t) janet_getinteger64(argv, 0); t = (time_t) janet_getinteger64(argv, 0);
} else { } else {
time(&t); time(&t);
} }
t_info = localtime(&t); #ifdef JANET_WINDOWS
localtime_s(&t_infos, &t);
t_info = &t_infos;
#else
t_info = localtime_r(&t, &t_infos);
#endif
JanetKV *st = janet_struct_begin(9); JanetKV *st = janet_struct_begin(9);
janet_struct_put(st, janet_ckeywordv("seconds"), janet_wrap_number(t_info->tm_sec)); janet_struct_put(st, janet_ckeywordv("seconds"), janet_wrap_number(t_info->tm_sec));
janet_struct_put(st, janet_ckeywordv("minutes"), janet_wrap_number(t_info->tm_min)); janet_struct_put(st, janet_ckeywordv("minutes"), janet_wrap_number(t_info->tm_min));

View File

@ -30,7 +30,8 @@ void *janet_v_grow(void *v, int32_t increment, int32_t itemsize) {
int32_t dbl_cur = (NULL != v) ? 2 * janet_v__cap(v) : 0; int32_t dbl_cur = (NULL != v) ? 2 * janet_v__cap(v) : 0;
int32_t min_needed = janet_v_count(v) + increment; int32_t min_needed = janet_v_count(v) + increment;
int32_t m = dbl_cur > min_needed ? dbl_cur : min_needed; int32_t m = dbl_cur > min_needed ? dbl_cur : min_needed;
int32_t *p = (int32_t *) janet_srealloc(v ? janet_v__raw(v) : 0, itemsize * m + sizeof(int32_t) * 2); size_t newsize = ((size_t) itemsize) * m + sizeof(int32_t) * 2;
int32_t *p = (int32_t *) janet_srealloc(v ? janet_v__raw(v) : 0, newsize);
if (!v) p[1] = 0; if (!v) p[1] = 0;
p[0] = m; p[0] = m;
return p + 2; return p + 2;

View File

@ -892,12 +892,12 @@ static JanetSignal run_vm(JanetFiber *fiber, Janet in, JanetFiberStatus status)
Janet fv = stack[C]; Janet fv = stack[C];
vm_assert_type(fv, JANET_FIBER); vm_assert_type(fv, JANET_FIBER);
JanetFiber *f = janet_unwrap_fiber(fv); JanetFiber *f = janet_unwrap_fiber(fv);
JanetFiberStatus status = janet_fiber_status(f); JanetFiberStatus sub_status = janet_fiber_status(f);
if (status > JANET_STATUS_USER9) { if (sub_status > JANET_STATUS_USER9) {
vm_throw("cannot propagate from new or alive fiber"); vm_throw("cannot propagate from new or alive fiber");
} }
janet_vm_fiber->child = f; janet_vm_fiber->child = f;
vm_return((int) status, stack[B]); vm_return((int) sub_status, stack[B]);
} }
VM_OP(JOP_PUT) VM_OP(JOP_PUT)

View File

@ -87,18 +87,18 @@ https://github.com/antirez/linenoise/blob/master/linenoise.c
/* static state */ /* static state */
#define JANET_LINE_MAX 1024 #define JANET_LINE_MAX 1024
#define JANET_HISTORY_MAX 100 #define JANET_HISTORY_MAX 100
static int israwmode = 0; static int gbl_israwmode = 0;
static const char *prompt = "> "; static const char *gbl_prompt = "> ";
static int plen = 2; static int gbl_plen = 2;
static char buf[JANET_LINE_MAX]; static char gbl_buf[JANET_LINE_MAX];
static int len = 0; static int gbl_len = 0;
static int pos = 0; static int gbl_pos = 0;
static int cols = 80; static int gbl_cols = 80;
static char *history[JANET_HISTORY_MAX]; static char *gbl_history[JANET_HISTORY_MAX];
static int history_count = 0; static int gbl_history_count = 0;
static int historyi = 0; static int gbl_historyi = 0;
static int sigint_flag = 0; static int gbl_sigint_flag = 0;
static struct termios termios_start; static struct termios gbl_termios_start;
/* Unsupported terminal list from linenoise */ /* Unsupported terminal list from linenoise */
static const char *badterms[] = { static const char *badterms[] = {
@ -121,8 +121,8 @@ static char *sdup(const char *s) {
static int rawmode() { static int rawmode() {
struct termios t; struct termios t;
if (!isatty(STDIN_FILENO)) goto fatal; if (!isatty(STDIN_FILENO)) goto fatal;
if (tcgetattr(STDIN_FILENO, &termios_start) == -1) goto fatal; if (tcgetattr(STDIN_FILENO, &gbl_termios_start) == -1) goto fatal;
t = termios_start; t = gbl_termios_start;
t.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); t.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
t.c_oflag &= ~(OPOST); t.c_oflag &= ~(OPOST);
t.c_cflag |= (CS8); t.c_cflag |= (CS8);
@ -130,7 +130,7 @@ static int rawmode() {
t.c_cc[VMIN] = 1; t.c_cc[VMIN] = 1;
t.c_cc[VTIME] = 0; t.c_cc[VTIME] = 0;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) < 0) goto fatal; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &t) < 0) goto fatal;
israwmode = 1; gbl_israwmode = 1;
return 0; return 0;
fatal: fatal:
errno = ENOTTY; errno = ENOTTY;
@ -139,8 +139,8 @@ fatal:
/* Disable raw mode */ /* Disable raw mode */
static void norawmode() { static void norawmode() {
if (israwmode && tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios_start) != -1) if (gbl_israwmode && tcsetattr(STDIN_FILENO, TCSAFLUSH, &gbl_termios_start) != -1)
israwmode = 0; gbl_israwmode = 0;
} }
static int curpos() { static int curpos() {
@ -171,7 +171,9 @@ static int getcols() {
if (cols > start) { if (cols > start) {
char seq[32]; char seq[32];
snprintf(seq, 32, "\x1b[%dD", cols - start); snprintf(seq, 32, "\x1b[%dD", cols - start);
if (write(STDOUT_FILENO, seq, strlen(seq)) == -1) {} if (write(STDOUT_FILENO, seq, strlen(seq)) == -1) {
exit(1);
}
} }
return cols; return cols;
} else { } else {
@ -182,7 +184,9 @@ failed:
} }
static void clear() { static void clear() {
if (write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7) <= 0) {} if (write(STDOUT_FILENO, "\x1b[H\x1b[2J", 7) <= 0) {
exit(1);
}
} }
static void refresh() { static void refresh() {
@ -190,38 +194,40 @@ static void refresh() {
JanetBuffer b; JanetBuffer b;
/* Keep cursor position on screen */ /* Keep cursor position on screen */
char *_buf = buf; char *_buf = gbl_buf;
int _len = len; int _len = gbl_len;
int _pos = pos; int _pos = gbl_pos;
while ((plen + _pos) >= cols) { while ((gbl_plen + _pos) >= gbl_cols) {
_buf++; _buf++;
_len--; _len--;
_pos--; _pos--;
} }
while ((plen + _len) > cols) { while ((gbl_plen + _len) > gbl_cols) {
_len--; _len--;
} }
janet_buffer_init(&b, 0); janet_buffer_init(&b, 0);
/* Cursor to left edge, prompt and buffer */ /* Cursor to left edge, gbl_prompt and buffer */
janet_buffer_push_u8(&b, '\r'); janet_buffer_push_u8(&b, '\r');
janet_buffer_push_cstring(&b, prompt); janet_buffer_push_cstring(&b, gbl_prompt);
janet_buffer_push_bytes(&b, (uint8_t *) _buf, _len); janet_buffer_push_bytes(&b, (uint8_t *) _buf, _len);
/* Erase to right */ /* Erase to right */
janet_buffer_push_cstring(&b, "\x1b[0K"); janet_buffer_push_cstring(&b, "\x1b[0K");
/* Move cursor to original position. */ /* Move cursor to original position. */
snprintf(seq, 64, "\r\x1b[%dC", (int)(_pos + plen)); snprintf(seq, 64, "\r\x1b[%dC", (int)(_pos + gbl_plen));
janet_buffer_push_cstring(&b, seq); janet_buffer_push_cstring(&b, seq);
if (write(STDOUT_FILENO, b.data, b.count) == -1) {} if (write(STDOUT_FILENO, b.data, b.count) == -1) {
exit(1);
}
janet_buffer_deinit(&b); janet_buffer_deinit(&b);
} }
static int insert(char c) { static int insert(char c) {
if (len < JANET_LINE_MAX - 1) { if (gbl_len < JANET_LINE_MAX - 1) {
if (len == pos) { if (gbl_len == gbl_pos) {
buf[pos++] = c; gbl_buf[gbl_pos++] = c;
buf[++len] = '\0'; gbl_buf[++gbl_len] = '\0';
if (plen + len < cols) { if (gbl_plen + gbl_len < gbl_cols) {
/* Avoid a full update of the line in the /* Avoid a full update of the line in the
* trivial case. */ * trivial case. */
if (write(STDOUT_FILENO, &c, 1) == -1) return -1; if (write(STDOUT_FILENO, &c, 1) == -1) return -1;
@ -229,9 +235,9 @@ static int insert(char c) {
refresh(); refresh();
} }
} else { } else {
memmove(buf + pos + 1, buf + pos, len - pos); memmove(gbl_buf + gbl_pos + 1, gbl_buf + gbl_pos, gbl_len - gbl_pos);
buf[pos++] = c; gbl_buf[gbl_pos++] = c;
buf[++len] = '\0'; gbl_buf[++gbl_len] = '\0';
refresh(); refresh();
} }
} }
@ -239,21 +245,21 @@ static int insert(char c) {
} }
static void historymove(int delta) { static void historymove(int delta) {
if (history_count > 1) { if (gbl_history_count > 1) {
free(history[historyi]); free(gbl_history[gbl_historyi]);
history[historyi] = sdup(buf); gbl_history[gbl_historyi] = sdup(gbl_buf);
historyi += delta; gbl_historyi += delta;
if (historyi < 0) { if (gbl_historyi < 0) {
historyi = 0; gbl_historyi = 0;
return; return;
} else if (historyi >= history_count) { } else if (gbl_historyi >= gbl_history_count) {
historyi = history_count - 1; gbl_historyi = gbl_history_count - 1;
return; return;
} }
strncpy(buf, history[historyi], JANET_LINE_MAX - 1); strncpy(gbl_buf, gbl_history[gbl_historyi], JANET_LINE_MAX - 1);
pos = len = strlen(buf); gbl_pos = gbl_len = strlen(gbl_buf);
buf[len] = '\0'; gbl_buf[gbl_len] = '\0';
refresh(); refresh();
} }
@ -261,62 +267,62 @@ static void historymove(int delta) {
static void addhistory() { static void addhistory() {
int i, len; int i, len;
char *newline = sdup(buf); char *newline = sdup(gbl_buf);
if (!newline) return; if (!newline) return;
len = history_count; len = gbl_history_count;
if (len < JANET_HISTORY_MAX) { if (len < JANET_HISTORY_MAX) {
history[history_count++] = newline; gbl_history[gbl_history_count++] = newline;
len++; len++;
} else { } else {
free(history[JANET_HISTORY_MAX - 1]); free(gbl_history[JANET_HISTORY_MAX - 1]);
} }
for (i = len - 1; i > 0; i--) { for (i = len - 1; i > 0; i--) {
history[i] = history[i - 1]; gbl_history[i] = gbl_history[i - 1];
} }
history[0] = newline; gbl_history[0] = newline;
} }
static void replacehistory() { static void replacehistory() {
char *newline = sdup(buf); char *newline = sdup(gbl_buf);
if (!newline) return; if (!newline) return;
free(history[0]); free(gbl_history[0]);
history[0] = newline; gbl_history[0] = newline;
} }
static void kleft() { static void kleft() {
if (pos > 0) { if (gbl_pos > 0) {
pos--; gbl_pos--;
refresh(); refresh();
} }
} }
static void kright() { static void kright() {
if (pos != len) { if (gbl_pos != gbl_len) {
pos++; gbl_pos++;
refresh(); refresh();
} }
} }
static void kbackspace() { static void kbackspace() {
if (pos > 0) { if (gbl_pos > 0) {
memmove(buf + pos - 1, buf + pos, len - pos); memmove(gbl_buf + gbl_pos - 1, gbl_buf + gbl_pos, gbl_len - gbl_pos);
pos--; gbl_pos--;
buf[--len] = '\0'; gbl_buf[--gbl_len] = '\0';
refresh(); refresh();
} }
} }
static int line() { static int line() {
cols = getcols(); gbl_cols = getcols();
plen = 0; gbl_plen = 0;
len = 0; gbl_len = 0;
pos = 0; gbl_pos = 0;
while (prompt[plen]) plen++; while (gbl_prompt[gbl_plen]) gbl_plen++;
buf[0] = '\0'; gbl_buf[0] = '\0';
addhistory(); addhistory();
if (write(STDOUT_FILENO, prompt, plen) == -1) return -1; if (write(STDOUT_FILENO, gbl_prompt, gbl_plen) == -1) return -1;
for (;;) { for (;;) {
char c; char c;
int nread; int nread;
@ -337,7 +343,7 @@ static int line() {
return 0; return 0;
case 3: /* ctrl-c */ case 3: /* ctrl-c */
errno = EAGAIN; errno = EAGAIN;
sigint_flag = 1; gbl_sigint_flag = 1;
return -1; return -1;
case 127: /* backspace */ case 127: /* backspace */
case 8: /* ctrl-h */ case 8: /* ctrl-h */
@ -352,8 +358,8 @@ static int line() {
kright(); kright();
break; break;
case 21: case 21:
buf[0] = '\0'; gbl_buf[0] = '\0';
pos = len = 0; gbl_pos = gbl_len = 0;
refresh(); refresh();
break; break;
case 26: /* ctrl-z */ case 26: /* ctrl-z */
@ -399,11 +405,11 @@ static int line() {
kleft(); kleft();
break; break;
case 'H': case 'H':
pos = 0; gbl_pos = 0;
refresh(); refresh();
break; break;
case 'F': case 'F':
pos = len; gbl_pos = gbl_len;
refresh(); refresh();
break; break;
} }
@ -413,11 +419,11 @@ static int line() {
default: default:
break; break;
case 'H': case 'H':
pos = 0; gbl_pos = 0;
refresh(); refresh();
break; break;
case 'F': case 'F':
pos = len; gbl_pos = gbl_len;
refresh(); refresh();
break; break;
} }
@ -435,9 +441,9 @@ void janet_line_init() {
void janet_line_deinit() { void janet_line_deinit() {
int i; int i;
norawmode(); norawmode();
for (i = 0; i < history_count; i++) for (i = 0; i < gbl_history_count; i++)
free(history[i]); free(gbl_history[i]);
historyi = 0; gbl_historyi = 0;
} }
static int checktermsupport() { static int checktermsupport() {
@ -450,9 +456,9 @@ static int checktermsupport() {
} }
void janet_line_get(const char *p, JanetBuffer *buffer) { void janet_line_get(const char *p, JanetBuffer *buffer) {
prompt = p; gbl_prompt = p;
buffer->count = 0; buffer->count = 0;
historyi = 0; gbl_historyi = 0;
FILE *out = janet_dynfile("out", stdout); FILE *out = janet_dynfile("out", stdout);
if (!isatty(STDIN_FILENO) || !checktermsupport()) { if (!isatty(STDIN_FILENO) || !checktermsupport()) {
simpleline(buffer); simpleline(buffer);
@ -464,7 +470,7 @@ void janet_line_get(const char *p, JanetBuffer *buffer) {
} }
if (line()) { if (line()) {
norawmode(); norawmode();
if (sigint_flag) { if (gbl_sigint_flag) {
raise(SIGINT); raise(SIGINT);
} else { } else {
fputc('\n', out); fputc('\n', out);
@ -473,10 +479,10 @@ void janet_line_get(const char *p, JanetBuffer *buffer) {
} }
norawmode(); norawmode();
fputc('\n', out); fputc('\n', out);
janet_buffer_ensure(buffer, len + 1, 2); janet_buffer_ensure(buffer, gbl_len + 1, 2);
memcpy(buffer->data, buf, len); memcpy(buffer->data, gbl_buf, gbl_len);
buffer->data[len] = '\n'; buffer->data[gbl_len] = '\n';
buffer->count = len + 1; buffer->count = gbl_len + 1;
replacehistory(); replacehistory();
} }