Skip to content

Commit 6133e9d

Browse files
committed
Fix compile crash when returning a string literal
This fixes a crash during compile-time when returning a string or array literal from a function. Now the compiler will give an error instead. See 1) here: http://forum.sa-mp.com/showthread.php?t=355877 --------- test code -------- native use(...); return_string() { new string[] = "string"; return string; } return_string_literal() { return "string"; // error 029: invalid expression, assumed zero } return_number() { return 0; } main() { new n = return_number(); // OK new s[100]; s = return_string(); // OK s = return_string_literal(); // error 033: array must be indexed (variable "s") use(n, s); } ----- end of test code -----
1 parent c20d9cb commit 6133e9d

File tree

1 file changed

+65
-61
lines changed

1 file changed

+65
-61
lines changed

source/compiler/sc1.c

Lines changed: 65 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5621,7 +5621,7 @@ static void doreturn(void)
56215621
if ((rettype & uRETVALUE)!=0) {
56225622
int retarray=(ident==iARRAY || ident==iREFARRAY);
56235623
/* there was an earlier "return" statement in this function */
5624-
if (sub==NULL && retarray || sub!=NULL && !retarray)
5624+
if ((sub==NULL && retarray && sym!=NULL) || sub!=NULL && !retarray)
56255625
error(79); /* mixing "return array;" and "return value;" */
56265626
if (retarray && (curfunc->usage & uPUBLIC)!=0)
56275627
error(90,curfunc->name); /* public function may not return array */
@@ -5634,76 +5634,80 @@ static void doreturn(void)
56345634
if (ident==iARRAY || ident==iREFARRAY) {
56355635
int dim[sDIMEN_MAX],numdim;
56365636
cell arraysize;
5637-
assert(sym!=NULL);
5638-
if (sub!=NULL) {
5639-
assert(sub->ident==iREFARRAY);
5640-
/* this function has an array attached already; check that the current
5641-
* "return" statement returns exactly the same array
5642-
*/
5643-
level=sym->dim.array.level;
5644-
if (sub->dim.array.level!=level) {
5645-
error(48); /* array dimensions must match */
5637+
if (sym==NULL) {
5638+
/* array literals cannot be returned directly */
5639+
error(29); /* invalid expression, assumed zero */
5640+
} else {
5641+
if (sub!=NULL) {
5642+
assert(sub->ident==iREFARRAY);
5643+
/* this function has an array attached already; check that the current
5644+
* "return" statement returns exactly the same array
5645+
*/
5646+
level=sym->dim.array.level;
5647+
if (sub->dim.array.level!=level) {
5648+
error(48); /* array dimensions must match */
5649+
} else {
5650+
for (numdim=0; numdim<=level; numdim++) {
5651+
dim[numdim]=(int)sub->dim.array.length;
5652+
if (sym->dim.array.length!=dim[numdim])
5653+
error(47); /* array sizes must match */
5654+
if (numdim<level) {
5655+
sym=finddepend(sym);
5656+
sub=finddepend(sub);
5657+
assert(sym!=NULL && sub!=NULL);
5658+
/* ^^^ both arrays have the same dimensions (this was checked
5659+
* earlier) so the dependend should always be found
5660+
*/
5661+
} /* if */
5662+
} /* for */
5663+
} /* if */
56465664
} else {
5665+
int idxtag[sDIMEN_MAX];
5666+
int argcount;
5667+
/* this function does not yet have an array attached; clone the
5668+
* returned symbol beneath the current function
5669+
*/
5670+
sub=sym;
5671+
assert(sub!=NULL);
5672+
level=sub->dim.array.level;
56475673
for (numdim=0; numdim<=level; numdim++) {
56485674
dim[numdim]=(int)sub->dim.array.length;
5649-
if (sym->dim.array.length!=dim[numdim])
5650-
error(47); /* array sizes must match */
5675+
idxtag[numdim]=sub->x.tags.index;
56515676
if (numdim<level) {
5652-
sym=finddepend(sym);
56535677
sub=finddepend(sub);
5654-
assert(sym!=NULL && sub!=NULL);
5655-
/* ^^^ both arrays have the same dimensions (this was checked
5656-
* earlier) so the dependend should always be found
5657-
*/
5678+
assert(sub!=NULL);
56585679
} /* if */
5680+
/* check that all dimensions are known */
5681+
if (dim[numdim]<=0)
5682+
error(46,sym->name);
56595683
} /* for */
5684+
/* the address of the array is stored in a hidden parameter; the address
5685+
* of this parameter is 1 + the number of parameters (times the size of
5686+
* a cell) + the size of the stack frame and the return address
5687+
* base + 0*sizeof(cell) == previous "base"
5688+
* base + 1*sizeof(cell) == function return address
5689+
* base + 2*sizeof(cell) == number of arguments
5690+
* base + 3*sizeof(cell) == first argument of the function
5691+
* ...
5692+
* base + ((n-1)+3)*sizeof(cell) == last argument of the function
5693+
* base + (n+3)*sizeof(cell) == hidden parameter with array address
5694+
*/
5695+
assert(curfunc!=NULL);
5696+
assert(curfunc->dim.arglist!=NULL);
5697+
for (argcount=0; curfunc->dim.arglist[argcount].ident!=0; argcount++)
5698+
/* nothing */;
5699+
sub=addvariable(curfunc->name,(argcount+3)*sizeof(cell),iREFARRAY,sGLOBAL,curfunc->tag,dim,numdim,idxtag);
5700+
sub->parent=curfunc;
56605701
} /* if */
5661-
} else {
5662-
int idxtag[sDIMEN_MAX];
5663-
int argcount;
5664-
/* this function does not yet have an array attached; clone the
5665-
* returned symbol beneath the current function
5702+
/* get the hidden parameter, copy the array (the array is on the heap;
5703+
* it stays on the heap for the moment, and it is removed -usually- at
5704+
* the end of the expression/statement, see expression() in SC3.C)
56665705
*/
5667-
sub=sym;
5668-
assert(sub!=NULL);
5669-
level=sub->dim.array.level;
5670-
for (numdim=0; numdim<=level; numdim++) {
5671-
dim[numdim]=(int)sub->dim.array.length;
5672-
idxtag[numdim]=sub->x.tags.index;
5673-
if (numdim<level) {
5674-
sub=finddepend(sub);
5675-
assert(sub!=NULL);
5676-
} /* if */
5677-
/* check that all dimensions are known */
5678-
if (dim[numdim]<=0)
5679-
error(46,sym->name);
5680-
} /* for */
5681-
/* the address of the array is stored in a hidden parameter; the address
5682-
* of this parameter is 1 + the number of parameters (times the size of
5683-
* a cell) + the size of the stack frame and the return address
5684-
* base + 0*sizeof(cell) == previous "base"
5685-
* base + 1*sizeof(cell) == function return address
5686-
* base + 2*sizeof(cell) == number of arguments
5687-
* base + 3*sizeof(cell) == first argument of the function
5688-
* ...
5689-
* base + ((n-1)+3)*sizeof(cell) == last argument of the function
5690-
* base + (n+3)*sizeof(cell) == hidden parameter with array address
5691-
*/
5692-
assert(curfunc!=NULL);
5693-
assert(curfunc->dim.arglist!=NULL);
5694-
for (argcount=0; curfunc->dim.arglist[argcount].ident!=0; argcount++)
5695-
/* nothing */;
5696-
sub=addvariable(curfunc->name,(argcount+3)*sizeof(cell),iREFARRAY,sGLOBAL,curfunc->tag,dim,numdim,idxtag);
5697-
sub->parent=curfunc;
5706+
address(sub,sALT); /* ALT = destination */
5707+
arraysize=calc_arraysize(dim,numdim,0);
5708+
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
5709+
/* moveto1(); is not necessary, callfunction() does a popreg() */
56985710
} /* if */
5699-
/* get the hidden parameter, copy the array (the array is on the heap;
5700-
* it stays on the heap for the moment, and it is removed -usually- at
5701-
* the end of the expression/statement, see expression() in SC3.C)
5702-
*/
5703-
address(sub,sALT); /* ALT = destination */
5704-
arraysize=calc_arraysize(dim,numdim,0);
5705-
memcopy(arraysize*sizeof(cell)); /* source already in PRI */
5706-
/* moveto1(); is not necessary, callfunction() does a popreg() */
57075711
} /* if */
57085712
} else {
57095713
/* this return statement contains no expression */

0 commit comments

Comments
 (0)