Feeds:
Posts
Comments

Archive for July, 2022

Ok, I know that starting it with a title like “int sign bit field issue” induces one to think that there is an issue with all this by definition.There is an issue, but in reality if one knows how the types works s|he probably won’t make this mistake at all, so, it’s not C fault, but the programmer that doesn’t care about computer arch or C specifications. But what is the so called issue? Let’s see.

Just imagine someone decides to create its own bool type. We know that stdbool exists today, but in the past it wasn’t there at all. Because this, many were those that created their own bool type. Now imagine that someone decides to save bits usage, what is a very altruist way to think, for sure. Imagine that s|he does like this:

#include <stdio.h>

#define t_bool signed int
#define FALSE 0
#define TRUE 1

typedef struct {
    t_bool a:1;
} bool;

t_bool is_even(int number) {
    if(number % 2 == 0)
        return TRUE;
    return FALSE;
}

int main(void) {
    bool b;

    b.a = TRUE;
    if (b.a) printf("%i\n", b.a);
    
    b.a = FALSE;
    if(!b.a) printf("%i\n", b.a);

    b.a = TRUE;
    if(b.a == is_even(4))
       printf("it works");
    else
       printf("Ooopsie!!!");
}

Did you spot anything that need to be care about? If not, no problem, this post is exactly about it. Let’s look at line 8. It declares a variable of type t_bool and shrinks it to a bit field of size 1 (one bit: 0 or 1). So far so good. The idea here was to use just one 1 bit to define a bool, since we just need either 1 or 0 bit set. But…I said but. If you run this program you’ll see that when a TRUE is set to b.a it is not truly true, well, in C it is kind of, since anything diff than zero is true expression. But if you have a function that returns TRUE and you need to check it against the b.a value? Yep, it is here where the things get messy.

If you run this program you’ll see something like:

-1
0
Ooopsie!!!

Yep. Definitely there is something wrong. See that I did declared explicitly t_bool as a signed int, but remember that if you say just int it is already a signed int. Ok, ok, but what is the point with the signed? Exactly. A signed type needs one bit to set the sign. Did you get the “AHA” ? Let’s show using a image 🙂

Let’s just simplify that a int size is 2 or 4 bytes arch depending. As the image shows a byte has 8 bits, and in a sign int one of the bits is used to set the sign.

In our code, we set type bool to be a 1 bit size. But wait, it is a sign int what happen with the sign? Exactly, nothing, it will be there, the real question would be: what happen with the value? It’s used to set the sign bit. That is why when you run that program you’ll see b.a = TRUE as -1 not 1, because you are setting the bit sign to 1, that means a negative sign.

There is plenty of vulnerabilities found around that are about signed and unsigned types. Some of them mostly happen because C is a kind of hard language in the sense of you need to know exactly what are you doing, and well, sorry for that, in the last years with all these high level languages developers get to be very slack and careless about how things works closely to the hardware (as C does).

References: This post was based on that twitter post.

Thanks! =)

Read Full Post »