-
Notifications
You must be signed in to change notification settings - Fork 84
Description
A copy of a literal array is not made on the heap before passing it to a function as an argument to a non-const qualified formal parameter. The changes made to the argument modify the array literal (this shouldn't be happening).
Example:
The following snippet highlights the issue:
#include <a_samp>
f(arr[]) {
printf("%s", arr);
arr[3] = 'Z';
}
wrapper() {
f("ABCDEFGHIK");
}
main () {
wrapper();
wrapper();
}
produces
ABCDEFGHIK
ABCZEFGHIK
Most people would expect "ABCDEFGHIK" to be passed in both the function calls. However, it does not. The compiler pushes the address of the literal array on to the stack and the function modifies the literal array. These changes are wrongly retained for future function calls.
What could be done?
A copy of the literal array has to be made on the heap while passing it as an argument to a non-const qualified formal parameter. This will ensure that any changes to the array will not be reflected in the future function calls (which is intended).
In case the formal parameter is const qualified, then a copy wouldn't be needed as the function guarantees that it will not modify the literal array.
Issues to be considered
-
could break scripts which rely on the bug
-
could add unnecessary performance cost to poorly written scripts (functions which are not const-correct, i.e: an array parameter which is not modified is not marked as const; this leads to unnecessary copying of the literal array on the heap)
More issues pointed out by Y_Less (#276 (comment)):
-
SAMP natives are not const correct
-
Adding a warning for unmodified non-const arrays will introduce new warnings in legacy code.
-
How would this be controlled for vararg functions? What is the correct behaviour for passing
"hi"
toF(...)
. The...
simply cannot be declaredconst
because not all the parameters may be constant, and there's no real way to determine which parameters are written to or not. Do you add the overhead of a copy to every string literal on the off-chance it is written to? -
Are there any demonstrable bugs changing this behaviour would have prevented?