Reputation: 1043
How can I check whether a memory address is writable or not at runtime?
For example, I want to implement is_writable_address in following code. Is it possible?
#include <stdio.h>
int is_writable_address(void *p) {
// TODO
}
void func(char *s) {
if (is_writable_address(s)) {
*s = 'x';
}
}
int main() {
char *s1 = "foo";
char s2[] = "bar";
func(s1);
func(s2);
printf("%s, %s\n", s1, s2);
return 0;
}
Upvotes: 7
Views: 4672
Reputation: 20725
Many Unix systems have had (and probably still have) the brk()
and sbrk()
functions defined (deprecated in POSIX since 2001). You can find the start of the memory data using &etext
or &edata
. You get the end with the sbrk()
function. If the address you want to access is between those two points, you can read and write at that memory address (with whatever consequence there is if you smash data in a struct--i.e. UB—Undefined Behavior).
extern char etext;
int is_writable_address(void *p) {
return p >= &etext && p < sbrk(0);
}
Note: as far as I know, newer systems that allow "huge pages" will allocate memory at locations that are not contiguous. So the above trick may fail on those.
Upvotes: -1
Reputation: 239011
I generally concur with those suggesting that this is a bad idea.
That said, and given that the question has the UNIX tag, the classic way to do this on UNIX-like operating systems is to use a read()
from /dev/zero
:
#include <fcntl.h>
#include <unistd.h>
int is_writeable(void *p)
{
int fd = open("/dev/zero", O_RDONLY);
int writeable;
if (fd < 0)
return -1; /* Should not happen */
writeable = read(fd, p, 1) == 1;
close(fd);
return writeable;
}
Upvotes: 10
Reputation:
It may be technically possible, but there is no portable way to do so, and it should never be necessary to do so. If you've managed to lose track of whether a pointer is writable or not, there's a bunch of even more important details that you don't know either, like what it points to, and whether your code should be writing to it or not.
Upvotes: -1