Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a C assert to make the code more secure?

Tags:

c

assert

Reading misc. tutorials related to SDL development I've found two different examples, doing the same thing, but in a different manner. I was wondering which of the two are you considering to be correct, judging from the perspective of code "security" and maintainability .

In the first example the programmer isn't using assert at all, but the code looks OK (at least for my eye):

int main(){
        SDL_Surface *screen;

        /** Initialize SDL */
        if(SDL_Init(SDL_INIT_VIDEO)!=0){
                fprintf(stderr,"Unable to initialize SDL: %s",SDL_GetError());
        }
        atexit(SDL_Quit);

        /** Sets video mode */
        screen=SDL_SetVideoMode(640,480,16,SDL_HWSURFACE);
        if(screen==NULL){
                fprintf(stderr,"Unable to set video mode: %s",SDL_GetError());
        }

        return (0);
}

In the second example the programmer [other] is using a different approach, something like (the code isn't exactly copy-paste):

int main(){
        SDL_Surface* screen;

        /** Initialize SDL */
        assert(SDL_Init(SDL_INIT_VIDEO)==0);
        atexit(SDL_Quit);

        /** Sets video mode */
        screen=SDL_SetVideoMode(640,480,16,SDL_HWSURFACE);
        assert(screen!=NULL);

        return (0);
}

Is it OK to "substitute" in the if conditions (from the first example) with asserts like in the second example ?

What's the right strategy (if there's any) ?

like image 335
Andrei Ciobanu Avatar asked Nov 28 '22 03:11

Andrei Ciobanu


2 Answers

It is not OK to do this substitution. The second example is wrong, because assert(x) gets expanded to nothing in non-debug builds (when NDEBUG is defined). This implies that the pointer checks in assert above are removed from the code in release builds. That is definitely wrong.

So, when should one use assert? It is useful for documenting and debugging. In a way, you're saying, "I am sure that this condition is true, and am putting it here as an assert to catch bad code during debugging, and to document the condition to the readers of the code".

So, there is a BIG difference between the two examples. For things like checking the return value of malloc, assert is wrong because there is no guarantee that they will return non-NULL, and as I have mentioned above, assert(x) means "I am completely sure x is true", and not just "If x is not true, it is bad". For this, one uses if(x) good(); else bad(); control.

SDL_Init and SDL_SetVideoMode can return -1 and NULL respectively.

like image 72
Alok Singhal Avatar answered Jan 12 '23 00:01

Alok Singhal


assert should be used when things go awry, in an unexpected way. Usually if an assertion fails, it means there is a bug in the program. Assertions are not used for expected errors that can just happen (i.e. failed to open a file, failed to initialize something, and so on).

In the example you presented, assert doesn't seem like the most logical solution. When the program failed to init SDL it makes more sense to tell it to the user in a structured way than to throw an assertion (which can just cause a seg-fault on some systems).

like image 27
Eli Bendersky Avatar answered Jan 11 '23 23:01

Eli Bendersky