Skip to content

Commit 9fccc47

Browse files
committed
Several leaks and bugs fixed (added new unit test)
1 parent b5fb934 commit 9fccc47

39 files changed

Lines changed: 658 additions & 88 deletions

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,5 @@ binding/GravityObjC/GravityObjC.xcodeproj/project.xcworkspace/xcshareddata/IDEWo
325325
gravity.xcodeproj/xcuserdata/marco.xcuserdatad/xcschemes/gravity.xcscheme
326326
*.xcscheme
327327
*.xcscheme
328+
gravity.xcodeproj/xcuserdata/marco.xcuserdatad/xcschemes/gravity.xcscheme
329+
*.d

src/compiler/gravity_codegen.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ static void report_error (gvisitor_t *self, gnode_t *node, const char *format, .
7777

7878
// build error message
7979
char buffer[1024];
80+
buffer[0] = 0;
8081
va_list arg;
8182
if (format) {
8283
va_start (arg, format);
@@ -2142,6 +2143,7 @@ gravity_function_t *gravity_codegen(gnode_t *node, gravity_delegate_t *delegate,
21422143
marray_pop(data.context);
21432144
assert(marray_size(data.context) == 0);
21442145
marray_destroy(data.context);
2146+
marray_destroy(data.superfix);
21452147

21462148
// in case of codegen errors explicity free code and return NULL
21472149
if (visitor.nerr != 0) {ircode_free(code); f->bytecode = NULL;}

src/compiler/gravity_ircode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ void ircode_dump (void *_code) {
293293
switch (n) {
294294
case 0: {
295295
printf("%05d\t%s\n", line, opcode_name(op));
296-
}
296+
} break;
297297

298298
case 1: {
299299
printf("%05d\t%s %d\n", line, opcode_name(op), p1);

src/compiler/gravity_lexer.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ typedef enum {
3939

4040
// LEXER macros
4141
#define NEXT lexer->buffer[lexer->offset++]; ++lexer->position; INC_COL
42-
#define PEEK_CURRENT ((int)lexer->buffer[lexer->offset])
42+
#define PEEK_CURRENT ((lexer->offset < lexer->length) ? (int)lexer->buffer[lexer->offset] : 0)
4343
#define PEEK_NEXT ((lexer->offset < lexer->length) ? lexer->buffer[lexer->offset+1] : 0)
4444
#define PEEK_NEXT2 ((lexer->offset+1 < lexer->length) ? lexer->buffer[lexer->offset+2] : 0)
4545
#define INC_LINE ++lexer->lineno; RESET_COL
@@ -184,9 +184,9 @@ static inline bool next_utf8(gravity_lexer_t *lexer, int *result) {
184184

185185
switch(len) {
186186
case 1: break;
187-
case 2: INC_OFFSET; INC_TOKBYTES; break;
188-
case 3: INC_OFFSET; INC_OFFSET; INC_TOKBYTES; INC_TOKBYTES; break;
189-
case 4: INC_OFFSET; INC_OFFSET; INC_OFFSET; INC_TOKBYTES; INC_TOKBYTES; INC_TOKBYTES; INC_POSITION; INC_TOKUTF8LEN; break;
187+
case 2: if (IS_EOF) return false; INC_OFFSET; INC_TOKBYTES; break;
188+
case 3: if (IS_EOF) return false; INC_OFFSET; if (IS_EOF) return false; INC_OFFSET; INC_TOKBYTES; INC_TOKBYTES; break;
189+
case 4: if (IS_EOF) return false; INC_OFFSET; if (IS_EOF) return false; INC_OFFSET; if (IS_EOF) return false; INC_OFFSET; INC_TOKBYTES; INC_TOKBYTES; INC_TOKBYTES; INC_POSITION; INC_TOKUTF8LEN; break;
190190
}
191191

192192
if (result) *result = c;
@@ -352,11 +352,14 @@ static gtoken_t lexer_scan_string(gravity_lexer_t *lexer) {
352352
// handle escaped characters
353353
if (c2 == '\\') {
354354
INC_OFFSET_POSITION;
355-
INC_OFFSET_POSITION;
356-
INC_TOKLEN;
357355
INC_TOKLEN;
358356

359357
// sanity check
358+
if (IS_EOF) return lexer_error(lexer, "Unexpected EOF inside a string literal");
359+
360+
INC_OFFSET_POSITION;
361+
INC_TOKLEN;
362+
360363
if (IS_EOF) return lexer_error(lexer, "Unexpected EOF inside a string literal");
361364
continue;
362365
}

src/compiler/gravity_optimizer.c

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
#define IS_NEG(inst) ((inst) && (inst->op == NEG))
2121
#define IS_NUM(inst) ((inst) && (inst->op == LOADI))
2222
#define IS_MATH(inst) ((inst) && (inst->op >= ADD) && (inst->op <= REM))
23-
#define IS_SKIP(inst) (inst->tag == SKIP_TAG)
24-
#define IS_LABEL(inst) (inst->tag == LABEL_TAG)
23+
#define IS_SKIP(inst) ((inst) && (inst->tag == SKIP_TAG))
24+
#define IS_LABEL(inst) ((inst) && (inst->tag == LABEL_TAG))
2525
#define IS_NOTNULL(inst) (inst)
2626
#define IS_PRAGMA_MOVE_OPT(inst) ((inst) && (inst->tag == PRAGMA_MOVE_OPTIMIZATION))
2727

@@ -325,15 +325,23 @@ static bool optimize_const_instruction (inst_t *inst, inst_t *inst1, inst_t *ins
325325

326326
case DIV:
327327
// don't optimize in case of division by 0
328-
if ((int64_t)d2 == 0) return false;
329-
if (type == DOUBLE_TAG) d = d1 / d2;
330-
else n = n1 / n2;
328+
if (type == DOUBLE_TAG) {
329+
if (d2 == 0.0) return false;
330+
d = d1 / d2;
331+
} else {
332+
if (n2 == 0) return false;
333+
n = n1 / n2;
334+
}
331335
break;
332336

333337
case REM:
334-
if ((int64_t)d2 == 0) return false;
335-
if (type == DOUBLE_TAG) d = (double)((int64_t)d1 % (int64_t)d2);
336-
else n = n1 % n2;
338+
if (type == DOUBLE_TAG) {
339+
if (d2 == 0.0) return false;
340+
d = (double)((int64_t)d1 % (int64_t)d2);
341+
} else {
342+
if (n2 == 0) return false;
343+
n = n1 % n2;
344+
}
337345
break;
338346

339347
default:

src/compiler/gravity_parser.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ static void report_error (gravity_parser_t *parser, error_type_t error_type, gto
168168

169169
// build error message
170170
char buffer[1024];
171+
buffer[0] = 0;
171172
va_list arg;
172173
if (format) {
173174
va_start (arg, format);

src/optionals/gravity_opt_env.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ static gravity_list_t *argv = NULL;
3535
*
3636
*/
3737
static bool gravity_env_get(gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
38-
#pragma unused(nargs)
39-
40-
if(!VALUE_ISA_STRING(args[1])) {
38+
if(nargs < 2 || !VALUE_ISA_STRING(args[1])) {
4139
RETURN_ERROR("Environment variable key must be a string.");
4240
}
4341

@@ -63,9 +61,7 @@ static bool gravity_env_get(gravity_vm *vm, gravity_value_t *args, uint16_t narg
6361
* @retval Weather this function was successful or not.
6462
*/
6563
static bool gravity_env_set(gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
66-
#pragma unused(nargs)
67-
68-
if(!VALUE_ISA_STRING(args[1]) || (!VALUE_ISA_STRING(args[2]) && !VALUE_ISA_NULL(args[2]))) {
64+
if(nargs < 2 || !VALUE_ISA_STRING(args[1]) || (!VALUE_ISA_STRING(args[2]) && !VALUE_ISA_NULL(args[2]))) {
6965
RETURN_ERROR("Environment variable key and value must both be strings.");
7066
}
7167

src/optionals/gravity_opt_file.c

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static gravity_file_t *gravity_ifile_new (gravity_vm *vm, FILE *f) {
5656

5757
static bool internal_file_size (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
5858
// 1 parameter of type string is required
59-
if (nargs != 2 && !VALUE_ISA_STRING(args[1])) {
59+
if (nargs != 2 || !VALUE_ISA_STRING(args[1])) {
6060
RETURN_ERROR("A path parameter of type String is required.");
6161
}
6262

@@ -67,7 +67,7 @@ static bool internal_file_size (gravity_vm *vm, gravity_value_t *args, uint16_t
6767

6868
static bool internal_file_exists (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
6969
// 1 parameter of type string is required
70-
if (nargs != 2 && !VALUE_ISA_STRING(args[1])) {
70+
if (nargs != 2 || !VALUE_ISA_STRING(args[1])) {
7171
RETURN_ERROR("A path parameter of type String is required.");
7272
}
7373

@@ -78,7 +78,7 @@ static bool internal_file_exists (gravity_vm *vm, gravity_value_t *args, uint16_
7878

7979
static bool internal_file_delete (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
8080
// 1 parameter of type string is required
81-
if (nargs != 2 && !VALUE_ISA_STRING(args[1])) {
81+
if (nargs != 2 || !VALUE_ISA_STRING(args[1])) {
8282
RETURN_ERROR("A path parameter of type String is required.");
8383
}
8484

@@ -89,7 +89,7 @@ static bool internal_file_delete (gravity_vm *vm, gravity_value_t *args, uint16_
8989

9090
static bool internal_file_read (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
9191
// 1 parameter of type string is required
92-
if (nargs != 2 && !VALUE_ISA_STRING(args[1])) {
92+
if (nargs != 2 || !VALUE_ISA_STRING(args[1])) {
9393
RETURN_ERROR("A path parameter of type String is required.");
9494
}
9595

@@ -106,7 +106,7 @@ static bool internal_file_read (gravity_vm *vm, gravity_value_t *args, uint16_t
106106

107107
static bool internal_file_write (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
108108
// 2 parameters of type string are required
109-
if (nargs != 3 && !VALUE_ISA_STRING(args[1]) && !VALUE_ISA_STRING(args[2])) {
109+
if (nargs != 3 || !VALUE_ISA_STRING(args[1]) || !VALUE_ISA_STRING(args[2])) {
110110
RETURN_ERROR("A path parameter of type String and a String parameter are required.");
111111
}
112112

@@ -119,7 +119,7 @@ static bool internal_file_write (gravity_vm *vm, gravity_value_t *args, uint16_t
119119

120120
static bool internal_file_buildpath (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
121121
// 2 parameters of type string are required
122-
if (nargs != 3 && !VALUE_ISA_STRING(args[1]) && !VALUE_ISA_STRING(args[2])) {
122+
if (nargs != 3 || !VALUE_ISA_STRING(args[1]) || !VALUE_ISA_STRING(args[2])) {
123123
RETURN_ERROR("A file and path parameters of type String are required.");
124124
}
125125

@@ -137,7 +137,7 @@ static bool internal_file_buildpath (gravity_vm *vm, gravity_value_t *args, uint
137137

138138
static bool internal_file_is_directory (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
139139
// 1 parameter of type string is required
140-
if (nargs != 2 && !VALUE_ISA_STRING(args[1])) {
140+
if (nargs != 2 || !VALUE_ISA_STRING(args[1])) {
141141
RETURN_ERROR("A path parameter of type String is required.");
142142
}
143143

@@ -148,7 +148,7 @@ static bool internal_file_is_directory (gravity_vm *vm, gravity_value_t *args, u
148148

149149
static bool internal_file_directory_create (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
150150
// 1 parameter of type string is required
151-
if (nargs != 2 && !VALUE_ISA_STRING(args[1])) {
151+
if (nargs != 2 || !VALUE_ISA_STRING(args[1])) {
152152
RETURN_ERROR("A path parameter of type String is required.");
153153
}
154154

@@ -218,12 +218,12 @@ static bool internal_file_directory_scan (gravity_vm *vm, gravity_value_t *args,
218218
// optional bool 2nd parameter
219219
int nindex = 2;
220220
bool recursive = true;
221-
if (VALUE_ISA_BOOL(args[2])) {
221+
if (nargs > 2 && VALUE_ISA_BOOL(args[2])) {
222222
recursive = VALUE_AS_BOOL(args[2]);
223223
nindex = 3;
224224
}
225-
226-
if (!VALUE_ISA_CLOSURE(args[nindex])) {
225+
226+
if (nargs <= (uint16_t)nindex || !VALUE_ISA_CLOSURE(args[nindex])) {
227227
RETURN_ERROR("A closure parameter is required.");
228228
}
229229

@@ -280,7 +280,7 @@ static bool internal_file_iread (gravity_vm *vm, gravity_value_t *args, uint16_t
280280
// var data = file.read(N)
281281

282282
// 1 parameter of type int is required
283-
if (nargs < 1 && (!VALUE_ISA_INT(args[1]) && !VALUE_ISA_STRING(args[1]))) {
283+
if (nargs < 2 || (!VALUE_ISA_INT(args[1]) && !VALUE_ISA_STRING(args[1]))) {
284284
RETURN_ERROR("A parameter of type Int or String is required.");
285285
}
286286

@@ -344,8 +344,8 @@ static bool internal_file_iread (gravity_vm *vm, gravity_value_t *args, uint16_t
344344
static bool internal_file_iwrite (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
345345
// var written = file.write(data)
346346

347-
// 1 parameter of type int is required
348-
if (nargs < 1 && !VALUE_ISA_STRING(args[1])) {
347+
// 1 parameter of type string is required
348+
if (nargs < 2 || !VALUE_ISA_STRING(args[1])) {
349349
RETURN_ERROR("A parameter of type String is required.");
350350
}
351351

@@ -360,7 +360,7 @@ static bool internal_file_iseek (gravity_vm *vm, gravity_value_t *args, uint16_t
360360
// var result = file.seek(offset, whence)
361361

362362
// 2 parameters of type int are required
363-
if (nargs != 3 && !VALUE_ISA_INT(args[1]) && !VALUE_ISA_INT(args[2])) {
363+
if (nargs != 3 || !VALUE_ISA_INT(args[1]) || !VALUE_ISA_INT(args[2])) {
364364
RETURN_ERROR("An offset parameter of type Int and a whence parameter of type Int are required.");
365365
}
366366

src/optionals/gravity_opt_json.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,10 @@ static bool JSON_parse (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
133133
gravity_string_t *string = VALUE_AS_STRING(value);
134134
json_value *json = json_parse(string->s, string->len);
135135
if (!json) RETURN_VALUE(VALUE_FROM_NULL, rindex);
136-
137-
RETURN_VALUE(JSON_value(vm, json), rindex);
136+
137+
gravity_value_t result = JSON_value(vm, json);
138+
json_value_free(json);
139+
RETURN_VALUE(result, rindex);
138140
}
139141

140142
//static bool JSON_begin_object (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {

src/optionals/gravity_opt_math.c

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ static bool math_xrt (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uin
223223
RETURN_VALUE(VALUE_FROM_INT(0), rindex);
224224
}
225225

226+
// check for division by zero in 1.0/base
227+
if ((VALUE_ISA_INT(base) && base.n == 0) || (VALUE_ISA_FLOAT(base) && base.f == 0.0)) {
228+
RETURN_VALUE(VALUE_FROM_UNDEFINED, rindex);
229+
}
230+
226231
if (VALUE_ISA_INT(value) && VALUE_ISA_INT(base)) {
227232
gravity_float_t computed_value = (gravity_float_t)pow((gravity_float_t)value.n, 1.0/base.n);
228233
RETURN_VALUE(VALUE_FROM_FLOAT(computed_value), rindex);
@@ -238,7 +243,7 @@ static bool math_xrt (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uin
238243
RETURN_VALUE(VALUE_FROM_FLOAT(computed_value), rindex);
239244
}
240245

241-
if (VALUE_ISA_FLOAT(value) && VALUE_ISA_INT(base)) {
246+
if (VALUE_ISA_FLOAT(value) && VALUE_ISA_FLOAT(base)) {
242247
gravity_float_t computed_value = (gravity_float_t)pow((gravity_float_t)value.f, 1.0/base.f);
243248
RETURN_VALUE(VALUE_FROM_FLOAT(computed_value), rindex);
244249
}
@@ -340,16 +345,14 @@ static bool math_floor (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, u
340345
}
341346

342347
static int gcf(int x, int y) {
343-
if (x == 0) {
344-
return y;
345-
}
348+
if (x < 0) x = -x;
349+
if (y < 0) y = -y;
350+
if (x == 0) return y;
351+
if (y == 0) return x;
346352
while (y != 0) {
347-
if (x > y) {
348-
x = x - y;
349-
}
350-
else {
351-
y = y - x;
352-
}
353+
int t = y;
354+
y = x % y;
355+
x = t;
353356
}
354357
return x;
355358
}
@@ -372,7 +375,8 @@ static bool math_gcf (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uin
372375
}
373376

374377
static int lcm(int x, int y) {
375-
return x*y/gcf(x,y);
378+
if (x == 0 || y == 0) return 0;
379+
return (x / gcf(x, y)) * y;
376380
}
377381

378382
static bool math_lcm (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {

0 commit comments

Comments
 (0)