Why is this C code section flagged as bad? [closed]

Any decent linter will flag numerous problems with this code. Here’s what the one provided with Atom editor found, plus what I eyeballed.

int lookup_personal_info(char *first_name, void *last_name, uint8_t (*sin)[9], const struct **info_out)
  • last_name is declared void * but used as a char *
  • const struct **info_out declares an anonymous struct. It should be personal_info **info_out
  • The function returns a bool not an int.
  • sin is never used except to check it’s passed in.
    if (!first_name || !last_name || !sin)
        return false;
  • Passing in a null pointer is probably a bug by the caller. This silently ignores that bug making it difficult to find. It should raise an error.
  • It forgets to check info_out.
    char *initials[3] = { first_name[0], last_name[1] };
  • This is an array of character pointers being initialized with char. It should be char initials[3].
  • It is not null terminated. Maybe it doesn’t have to be, but I wouldn’t risk that.
  • last_name is declared void * yet used as a char *.
  • It’s using the first character of first_name as an initial, that makes sense, but why the second… thing… in last_name?
    personal_info *data = malloc(sizeof(struct personal_info));

struct personal_info is not a type, the type is personal_info.

    *info_out = (personal_info *) data;

info_out was incorrectly declared as an anonymous struct. It should be personal_info **info_out. Then no type cast is necessary.

    bool is_ok = database_lookup(initials, &data);
    if (is_ok)
        goto fail;

The check is backwards.

The use of goto is justified to ensure proper cleanup on error. It’s probably included in the example as a red herring.

fail:
    data = NULL;
    free(data);

    return true;
  • free is called after nulling out data leaking memory.
  • There’s no need to set data to NULL, it’s local to the function which will shortly exit.
  • Both failure and success return true.

Leave a Comment