views:

216

answers:

4

In C can a function expose memory that it "manageds" at a lower level as readonly to those calling that function (exposing its address). return * const is not effective but I wondered if I was overlooking a programming tick?

Thanks.

const uint8_t * get_value(int index) 
{
static uint8_t data[2] = {0, 0};
return (const uint8_t *)&data[index];
}

int main(void)
{
uint8_t * value;
value = get_value(1);

*value += 1;
return 0;
}

@j_random_hacker Suggested a good compromise to my question that gives that extra barrier I'm looking for to prevent casual mis-use of that data.

typedef struct
{
    const uint8_t * value;
    const uint8_t size;

} readonly_t;

readonly_t get_value(int index, int size) 
{
    static uint8_t data[2] = {0, 0};
    uint8_t rsize;

    /* ... validate index, size params */

    readonly_t r = { &data[index], rsize };
    return r;
}
+1  A: 

Use VirtualProtect: http://msdn.microsoft.com/en-us/library/aa366898(VS.85).aspx

With PAGE_READONLY: http://msdn.microsoft.com/en-us/library/aa366786(VS.85).aspx

jeffamaphone
platform dependent and allocation granularity >= 4KB. But if that's not a problem... :)
peterchen
Not working on MS platform, far from it. Using an OSEK OS and vanilla C, no standard libraries etc.
Oliver
Yeah, its kind of a skeezy answer, I agree. But I figured other people would point out its impossibility in C. Of course callers can always use VirtualProtect() to change the status. The best thing to do is return a handle of some sort and map that to the opaque data structure internally.
jeffamaphone
+6  A: 

It's C! You can't :) There is always a way to circumvent it. Just make it const and hope somebody will not change it.

If you are hosting an add-in or something, you should run it in a separate process to limit its access to memory.

Mehrdad Afshari
Marked answer because you are technically right - I can't achieve real read-only functionality in this scenario. Thanks for your input
Oliver
+1  A: 

Don't return a pointer, return the pointed to object's value as in:

uint8_t get_value(int index) 
{
    static uint8_t data[2] = {0, 0};
    return data[index];
}
dirkgently
I would but this could be n-bytes in length e.g a structure
Oliver
Then, what you already have is the best you could with this language.
dirkgently
If n is fixed, you can wrap the array in a struct and return that by-value. C allows structs to be treated as first-class values (they can be assigned with =, passed to and returned from functions) but not arrays for some reason.
j_random_hacker
Because arrays have value context only under very special conditions (the sizeof operator being one) and decay to a pointer to the first object of the array in all other cases.
dirkgently
@j_random_hacker: I like your approach. However, the problem with struct-izing is a) memory create/copy overhead b) change every API or get into ugly casts.
dirkgently
@dirkgently: True, wrapping-in-a-struct is more than likely not the best solution. Just thought I'd mention it for completeness :)
j_random_hacker
A: 

Memory protection is not a language construct in 'C, it is something to do with the hardware. For example, if the memory pointed to by the pointer is in some ROM area or something, writing is not possible. And on the other way round, we can even make the part of the ReadOnly at the hardware level, then you can expect some memory exception.

Alphaneo