xintvl
xintvl

Reputation: 33

Signal SIGSEGV recieved: vfprintf.c: No such file or directory?

GCC return no errors or warnings. The program segfaults after entering a password over 21 characters. At first I had:

hash_p = SuperFastHash(query.pwd, strlen(query.pwd));

get this warning from GCC:

warning: assignment makes pointer from integer without a cast [-Wint-    conversion]
hash_p = SuperFastHash(query.pwd, strlen(query.pwd));
           ^

so I changed it to:

sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd)));

because the hash function returns an int. strcmp compares two type const char *.

When I debug the program using gdb, it returns this:

Program received signal SIGSEGV, Segmentation fault.
0xb7e500d5 in _IO_vfprintf_internal (s=<optimized out>, format=<optimized out>, 
ap=0xbffff46c "\261\a@") at vfprintf.c:1636
1636    vfprintf.c: No such file or directory.

Program:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdarg.h>
#include <stdint.h>

#define BUF_SIZE 1024
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif

#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
                   +(uint32_t)(((const uint8_t *)(d))[0]) )
#endif

uint32_t SuperFastHash (const char * data, int len) {
uint32_t hash = len, tmp;
int rem;

    if (len <= 0 || data == NULL) return 0;

    rem = len & 3;
    len >>= 2;

    for (;len > 0; len--) {
        hash  += get16bits (data);
        tmp    = (get16bits (data+2) << 11) ^ hash;
        hash   = (hash << 16) ^ tmp;
        data  += 2*sizeof (uint16_t);
        hash  += hash >> 11;
    }

    switch (rem) {
        case 3: hash += get16bits (data);
                hash ^= hash << 16;
                hash ^= ((signed char)data[sizeof (uint16_t)]) << 18;
                hash += hash >> 11;
                break;
        case 2: hash += get16bits (data);
                hash ^= hash << 11;
                hash += hash >> 17;
                break;
        case 1: hash += (signed char)*data;
                hash ^= hash << 10;
                hash += hash >> 1;
    }

    hash ^= hash << 3;
    hash += hash >> 5;
    hash ^= hash << 4;
    hash += hash >> 17;
    hash ^= hash << 25;
    hash += hash >> 6;

    return hash;
}


struct log_n {
        char uid[BUF_SIZE];
        char pwd[BUF_SIZE];
};

struct log_n acc[1] = {
        "username","-1257730142"
};

struct log_n query;

int main() {

    char *hash_p;      

    do {
            do{
                    printf("Username: ");
                    fgets(query.uid, sizeof query.uid, stdin);
                    query.uid[strcspn(query.uid, "\n")] = '\0';
                    if (strlen(query.uid) < 4) {
                            printf("Username must be between four and eight characters.\nTry again.\n");
                    }
                    if (strlen(query.uid) > 8) {
                            printf("Username must be less than eight characters.\nTry again.\n");
                    }
            } while (strlen(query.uid) < 4 || strlen(query.uid) > 8);

            do{
                    printf("Password: ");
                    fgets(query.pwd, sizeof query.pwd, stdin);
                    query.pwd[strcspn(query.pwd, "\n")] = '\0';
                    sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd)));

                    if (strlen(query.pwd) < 21) {
                            printf("Password must be atleast twenty-one characters long.\nTry again.\n");
                    }
            } while (strlen(query.pwd) < 21);
    } while (strcmp(query.uid, acc->uid) !=0 || strcmp(hash_p, acc->pwd) !=0);
}

Note: this is not a homework assignment. I am just a person learning C with help of people using the internet.

Upvotes: 3

Views: 10522

Answers (2)

Attie
Attie

Reputation: 6989

SuperFastHash() explicitly returns an unsigned 32-bit integer (uint32_t). Why are you printing that to a string and comparing / storing strings?

It would make more sense to just store and compare the numeric values.


You are currently confusing the pwd field of your struct:

  • acc[0].pwd stores a hash
  • query.pwd stores the plaintext password

If for some reason, you do want to store the number as a string (perhaps in a file), then please do it correctly!

An unsigned value will never be negative (your struct initialization specifies -1257730142).

char input_pwd[] = "my password";
uint32_t input_hash;
char hash_str[11]; /* 32-bit unsigned int can't be more than 10 characters, +1 for nul */

input_hash = SuperFastHash(input_pwd, strlen(input_pwd));
snprintf(hash_str, sizeof(hash_str), "%" PRIu32, input_hash);

In most cases you could get away with "%u" as the format string, but "%" PRIu32 is safer / more correct.


As pointed out below by gcc, your struct initialization is incorrect, and currently works "by mistake".

Did you mean this:

struct log_n acc[1] = {
        { "username", "3037237154" }
};

or this:

struct log_n acc = {
        "username", "3037237154"
};

Additionally, gcc will point you at your mistake if you compile with -Wall (to enable all warnings) - a very good habit to get into:

'hash_p' is used uninitialized in this function
$ gcc main.c -o main -Wall
main.c:72:23: warning: missing braces around initializer [-Wmissing-braces]
 struct log_n acc[1] = {
                       ^
main.c:72:23: note: (near initialization for 'acc')
main.c: In function 'main':
main.c:99:21: warning: 'hash_p' is used uninitialized in this function [-Wuninitialized]
                     sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd)));
                     ^

Finally, the vfprintf.c: No such file or directory message is informing you that GDB can't find the sources for printf(), which in this case is unrelated to your problem.

If you are going to be using GDB, then it's always a good idea to compile with -g to include the debug information in your binary.

Upvotes: 0

Jabberwocky
Jabberwocky

Reputation: 50911

In this line:

sprintf(hash_p, "%d", SuperFastHash(query.pwd, strlen(query.pwd)));

hash_p has never been initialized. It points nowhere.

Just replace char *hash_p; by char hash_p[20]. I'm not sure what the maximum length of the hash is (I assumed 20), so maybe 20 should be replaced by a more appropriate value.

Upvotes: 3

Related Questions