Variable receiving trash

Asked

Viewed 155 times

0

Considering this simple password validator in C:


    #include <stdio.h>
    #include <string.h> 
     
    int main(void)
    {     
    char buff[5];     
    int pass = 0; 
     
    printf("\n Entre com a senha : \n");     
    gets(buff); 
     
    if (strcmp(buff, "1234"))
    {         
        printf ("\n Senha Errada \n");     
    }  
    else   
    {         
        printf ("\n Senha Correta \n");         
        pass = 1;     
    } 
    
    if (pass) /* O usuário acertou a senha, poderá continuar*/ 
    {                
        printf ("\n Acesso Liberado \n");     
    } 
    else
    {         
        printf ("\n Acesso Negado \n");     
    } 
     
    return 0; 
    }  

If I enter the following password:

123456

the exit is:

Senha Errada
Acesso Liberado

Why access is being released if the password is wrong?

I know that the way the code is written, the string 123456 bursts the vector preventing the correct functioning of the function strcmp() because of the absence of '\0', but if the program prints Senha Errada, also means that pass = 0 and access denied, no?

I did the debug in Codeblocks, for some reason, when I put the password 123456 the variable pass is filled with garbage, in this case 54. My question is: why to burst the vector buff the variable pass is affected?

2 answers

4

After further analyzing the question, the problem really was another. In fact the if was right, but as it was done in the illegible way I quote below I ended up confusing myself, I’ll leave because it can help a lot of people, I’ve seen do this.

There is no problem with the terminator, not the indicated absence. There is the use of something that has long been considered obsolete because it is unsafe (gets()), see How to read from stdin in C? (also help). If you use a safe function, in the safe way this will not happen because there will be a limitation and it will not burst memory occupying space of something that is important for the plication to keep the information.

More information about the overflow in What is the buffer overflow?.


The documentation of strcmp() says it goes back 0 to when the comparison is equal and 1 or -1 if it is different. A if expecting a true to enter the next block and false to avoid the block of the if and leave without doing anything or to enter the else when there is, which is the case.

C is a weak typing language so it makes coercion of implicit types under certain rules. For example numerical types can turn Boolean, even because originally Booleans did not even exist in C and the number was and is used for this. So 0 is like a false, and any other number is true.

Comparing now:

strcmp()               if
    0 => igual             0 => false
não 0 => diferente     não 0 => true

Then if the function indicates that strings are equal gives false and if they are different gives true.

So you have to do:

!strcmp(buff, "1234")

or

strcmp(buff, "1234") == 0

to clarify and avoid certain problems in some scenarios.

I put in the Github for future reference.

The first reverses the boolean value and the second buy against the number you expect to be true. Another way is to invert the block code of the if and of else, but usually gets more confused.

  • Good afternoon, Maniero. My doubt is not about using strcmp itself. I believe I used it correctly. The problem is when I place a string larger than the vector supports it is changing the variable pass. I debugged the codeblocks, for some reason, when I put the password "123456" the variable pass is filled by garbage, in this case "54". My question is: why when bursting the Buff vector the pass variable is affected?

  • I edited to put a link, this is another problem, I just realized now because the less readable form fooled me.

  • Regarding illegibility. Do you mean the question, the code, or both? I edited a little after reading some guides here in the OS, I tried to make it more readable. Thanks for the touch.

  • @Gustavooliveira the code, you do the execution in an unintuitive way, because the most common is you seek to do what is true before. The question is ok.

4


Your doubt refers to: why the variable is filled in pass by passing the maximum rate of buff.

These two variables are in the stack. They are stored in order, following the FILO system (First In, Last Out).

Imagine that in memory is organized as follows (sorry the image quality :():

inserir a descrição da imagem aqui

Since the index is based on zero, we have the available indices of 0~4, of which 4° should be for the \0.

When you pass the index, you are writing in memory that does not belong to your buffer. In your case, as the image above describes, pass comes right after (in memory order). This can cause much more serious problems. Imagine if it was a pointer there? Probably the value pointed would be an invalid value, and when you tried to access it, it would cause Access Violation.

This way, when you typed 123456, the organization in memory was the following:

inserir a descrição da imagem aqui

Note that the value "6" is at the position of the first byte of pass. What it actually contains is an ASCII code representing 6.

According to the ASCII table: inserir a descrição da imagem aqui

The value 6 is 54 in DEC.

And that’s why you see 54 in pass

  • I get it. But in case I enter the password 12345. The pass will guard the \0? I did here and testified, the comparison came false, as expected. And pass continued with the value 0 normally.

  • Yes, you have overwritten the memory with 0. By chance it turned out to be the expected result, but you can never trust that

Browser other questions tagged

You are not signed in. Login or sign up in order to post.