Is it possible to get a segmentation error by accessing allocated, but uninitialized data in old regular c? I can't see how

0

Should be a straightforward question I think, but just in case context helps I'll add some info below:

I was developing a module for someone else and the module crashed via a segmentation error that occurred during a pthread_mutex_unlock(lock); call. I do not implement pthreads in my code at all, and the calling function is theoretically impossible to create a segmentation error with from what I can see:

bool IsValidTeam(Team4v4Data* td)//pthread_mutex_unlock(mutex* lock) segfaulted here on the log
{
    if (!td)
        return false;
    else if (strncmp (td->captain, "INVALID_CAPTAIN", NAMESIZE) == 0)
        return false;

    //we checked for a null pointer and for the struct w/name  that should be passed during an error,
    //"INVALID_CAPTAIN", as the name, could get a non-null bad pointer but calling function 
    //should handle that in 100% of cases

    //if we did receive bad data though, we never got to the end of this function to the caller
    return true;
}

The calling function should never return anything other than valid data for the IsValidTeam call though:

Team4v4Data* GetCaptainsTeam(Player* p)
{
    MyArenaData* mad = P_ARENA_DATA(arena4v4, arenaKey); //not mine and always works
    
    FOR_EACH_TEAM(t)//#defined as: for (int t = 0; t < MAXTEAMS; t++)
    {
        if (strncmp(mad->team[t].captain, p->name, NAMESIZE) == 0)
        {
            return &mad->team[t];
        }
    }
    //if we got here, none of the teams matched the players name
    //possible returns: a valid team object that matches the players name,
    //or this invalid team object containing td->captain is "INVALID_CAPTAIN"        
    return &mad->INVALID_TEAM;
}

And the caller's caller:

void Cready(Player* p, params* par, Target* targ, Arena* arena)//unsure of parameters, should be right
{
    Team4v4Data* td = GetCaptainsTeam(p);
    if (!IsValidTeam(td))//segmentation fault here
    {
        td->ready = true;
    }
    //else
        //notify players an error occurred and re-initialize/return the module 
        //to prevent further ones
    
    //do some processing, never got here
}

And rough outline of the structs:

typedef struct MyArenaData
{
    Team4v4Data team[MAXTEAMS];
    Team4v4Data INVALID_TEAM;//used for error checking in function returns instead of null pointer
//other random bools and data
} MyArenaData;

typedef struct Team4v4Data
{
    char captain[20];//normally initialized to "", but failed to initialize due to bug
    Player4v4Data slots[MAXPLAYERS];//has its own initializers, not used during our error though

//other random bools and data
} Team4v4Data;

typedef struct Player4v4Data
{
    char name[20];//normally initialized to "", but failed to initialize due to bug
    //other player stats
}

So when the error occurred, we discovered the data in the locations for the team and arena data was uninitialized due to a mislabeled function. However, I don't think it is possible that the data being accessed could cause a segmentation error because even if not initialized, it should still be the "correct" memory location for that data - any read or write operations may cause "unintended behavior", but the program should not ever be going past its buffer or reading/writing random memory locations because the pointers should always point to a valid data area, by design.

My question is: Am I correct in this thinking? Is it possible this seg fault originated from my code, or is it "must be something else" in the module handler because of the safety mechanisms in place being unable to access outside memory in this instance?

Also, any suggestions about null pointer safety or better data checking ideas are welcome. Thanks for looking.

EDIT: crash log:

Program received signal SIGSEGV, Segmentation fault.
__pthread_mutex_unlock_usercnt (mutex=0xffffffff, decr=1) at pthread_mutex_unlock.c:41 41      pthread_mutex_unlock.c: No such file
or directory. (gdb) bt
#0  __pthread_mutex_unlock_usercnt (mutex=0xffffffff, decr=1) at pthread_mutex_unlock.c:41
#1  0xf3a0465a in Cready (command=0xffffce3c "ready", params=0x82b3aa8 "\003", p=0xffffd084, target=0x0) at 4v4mod/4v4mod.c:327
#2  0x0807b5bf in run_commands (text=0x8380adf "", p=0x82b3aa8, target=0xffffd084, sound=0) at core/chat.c:366
#3  0x0807b9fd in handle_pub (p=0x82b3aa8, msg=0x8380ad9 "?ready", ismacro=0, isallcmd=0, sound=0) at core/chat.c:448
#4  0x0807c5c9 in PChat (p=0x82b3aa8, pkt=0x8380ad4 "\006\002", len=12) at core/chat.c:667

(gdb) frame 1
#1  0xf3a0465a in Cready (command=0xffffce3c "ready", params=0x82b3aa8 "\003", p=0xffffd084, target=0x0) at 4v4mod/4v4mod.c:327 327          
if (!IsValidTeam(td)) //player was not a captain, do nothing (gdb)
info locals td = 0xffffffff mad = 0xdfd7c300 (gdb) info args command =
0xffffce3c "ready" params = 0x82b3aa8 "\003" p = 0xffffd084 target =
0x0
c
pointers
struct
segmentation-fault
pthreads
asked on Stack Overflow Jul 14, 2020 by Plaje • edited Jul 14, 2020 by Plaje

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0