Is there any other compiler that writes to the pointer and does not take any memory breach failure using the processor in protected mode?
GCC 3 and earlier used to support gcc -fwriteable-strings
to let you compile old K&R C where this was apparently legal, according to https://gcc.gnu.org/onlinedocs/gcc-3.3.6/gcc/Incompatibilities.html. (It's undefined behaviour in ISO C and thus a bug in an ISO C program). That option will define the behaviour of the assignment which ISO C leaves undefined.
GCC 3.3.6 manual - C Dialect options
-fwritable-strings
Store string constants in the writable data segment and don't uniquize them. This is for compatibility with old programs which assume they can write into string constants.
Writing into string constants is a very bad idea; “constants” should be constant.
GCC 4.0 removed that option (release notes); the last GCC3 series was gcc3.4.6 in March 2006. Although apparently it had become buggy in that version.
gcc -fwritable-strings
would treat string literals like non-const anonymous character arrays (see @gnasher's answer), so they go in the .data
section instead of .rodata
, and thus get linked into a segment of the executable that's mapped to read+write pages, not read-only. (Executable segments have basically nothing to do with x86 segmentation, it's just a start+range memory-mapping from the executable file to memory.)
And it would disable duplicate-string merging, so char *foo() { return "hello"; }
and char *bar() { return "hello"; }
would return different pointer values, instead of merging identical string literals.
Related:
Linker option: still Undefined Behaviour so probably not viable
On GNU/Linux, linking with ld -N
(--omagic
) will make the text (as well as data) section read+write. This may apply to .rodata
even though modern GNU Binutils ld
puts .rodata
in its own section (normally with read but not exec permission) instead of making it part of .text
. Having .text
writeable could easily be a security problem: you never want a page with write+exec at the same time, otherwise some bugs like buffer overflows can turn into code-injection attacks.
To do this from gcc, use gcc -Wl,-N
to pass on that option to ld when linking.
This doesn't do anything about it being Undefined Behaviour to write const
objects. e.g. the compiler will still merge duplicate strings, so writing into one char *foo = "hello";
will affect all other uses of "hello"
in the whole program, even across files.
What to use instead:
If you want something writeable, use static char foo[] = "hello";
where the quoted string is just an array initializer for a non-const array. As a bonus, this is more efficient than static char *foo = "hello";
at global scope, because there's one fewer level of indirection to get to the data: it's just an array instead a pointer stored in memory.
"aaa"
is placed in read-only memory, which will result in a run-time error if you try to modify it. Also, if you have another instance of the string"aaa"
in the same compilation unit, they might share the same storage, in which case changing one will change the other. – Hankeringconst
in K&R C). By default Turbo-C didn't merge duplicate string literals which allowed them to be written to without clobbering the string literal for someone else (this allowed code written for K&R C to work as expected). You could turn duplicate merging on with the-d
option at which point you don't want to be writing them and they should be considered pointers to constant data. – Heinrick