/* { dg-do run } */ /* SEGV at comment below. */ typedef unsigned int size_t; typedef enum har { he_fatal = (-199), he_not_initialized, he_bad_input, he_memory_too_small, he_bad_action, he_duplicate, he_bad_nonce, he_stale_nonce, he_bad_credentials, he_bad_user, he_no_such_user, he_bad_passwd, he_unknown_auth_scheme, he_not_found, he_failed_digest_file_check, he_failed_digest_file_save, he_process_not_privileged, he_other, he_end_of_range, ha_no_error = 0, ha_no_value = 1 } har; typedef enum realm_type { axis_realm = 0, ws_realm } realm_type; __attribute__((__noclone__, __noinline__)) har has_www_auth(char *, size_t, realm_type, har); __attribute__((__noclone__, __noinline__)) har has_auth_user(const char *, const char *, realm_type, char *, size_t); __attribute__((__noclone__, __noinline__)) char *ha_get_string_value(void); typedef struct { unsigned int track_id; char* user; char* realm; char* authent; int internal_realm; } request; enum user_response { file_not_found_user_response = -3, access_denied_user_response = -2, no_user_response = -1, ok_user_response = 0 }; struct realm_group { char *name; int id; struct realm_group *next; }; struct realm { char *name; char *space; struct realm_group *groups; struct realm *next; }; struct user_info { char *name; int no_groups; int groups[128]; struct user_info *next; }; static struct user_info *find_user(const char *user_name); static int is_member_of_groups(const struct user_info *user_item, const struct realm_group *groups); int authent_author(request *req); struct realm *realms = ((void *)0); struct user_info *users = ((void *)0); static struct user_info* find_user(const char *user_name) { struct user_info *user_item; user_item = users; while (user_item != ((void *)0)) { /* SEGV due to NULL access here on user_name. See also comment below. */ if ((__builtin_strcmp(user_item->name, user_name) == 0)) break; user_item = user_item->next; } return user_item; } static int is_member_of_groups(const struct user_info *user_item, const struct realm_group *groups) { const struct realm_group *group_item; int i; group_item = groups; while (group_item != ((void *)0)) { for (i = 0; i < user_item->no_groups; i++) if (user_item->groups[i] == group_item->id) return 0; group_item = group_item->next; } return -1; } char *foo (void) __attribute__((__noclone__, __noinline__)); char* g_strdup (const char *str) __attribute__((__malloc__, __noclone__, __noinline__)); int g_strcmp0 (const char *str1, const char *str2); static int is_basic(char **user) { char *passwd_ptr; char *authent = foo(); passwd_ptr = __builtin_strchr(authent, ':'); if (passwd_ptr != ((void *)0)) { *user = g_strdup(authent); return 0; } return -1; } static int is_digest(char **user) { int ret_val = -1; char *authent; authent = ha_get_string_value(); if (authent) { *user = g_strdup(authent); ret_val = 0; } return ret_val; } __attribute__((__noclone__, __noinline__)) void g_free (void * mem); static enum user_response get_user_info_from_header(const realm_type type, char **user_name, struct user_info **user_item) { int ret_val = no_user_response; if ((type == ws_realm)) { if (is_basic(user_name) == 0) ret_val = access_denied_user_response; if (is_digest(user_name) == 0) ret_val = ok_user_response; } else { if (is_basic(user_name) < 0 && /* Load of *user_name here, but not after the is_digest call. */ is_digest(user_name) < 0) ; else if ((*user_item = find_user(*user_name)) != ((void *)0)) ret_val = ok_user_response; else ret_val = access_denied_user_response; if (ret_val != ok_user_response) g_free(*user_name); } return ret_val; } static enum user_response authenticate_user(request *req, char **user_name, struct user_info **user_item) { char *authent = ((void *)0); har resp = ha_no_value; enum user_response user_resp; int ret_val = no_user_response; if (req->authent && __builtin_strlen(req->authent)) { authent = req->authent; user_resp = get_user_info_from_header(req->internal_realm, user_name, user_item); if (user_resp == ok_user_response) { resp = has_auth_user(authent, 0, req->internal_realm, "", 1); if (resp == ha_no_error) ret_val = ok_user_response; else if (resp != he_stale_nonce) ret_val = access_denied_user_response; } else if (user_resp == access_denied_user_response) ret_val = access_denied_user_response; } if (resp != he_memory_too_small && resp != ha_no_error) resp = has_www_auth("", 1, req->internal_realm, resp); return ret_val; } int __attribute__ ((__noinline__, __noclone__)) authent_author(request *req) { struct realm *realm; char *user_name = ((void *)0); struct user_info *user_item = ((void *)0); int res = 0; asm (""); realm = realms; if (__builtin_strcmp("Wsd", realm->name) == 0) { req->internal_realm = ws_realm; is_digest(&user_name); } if (authenticate_user(req, &user_name, &user_item) < 0) { if (user_name != ((void *)0)) req->user = user_name; res = -2; goto authent_author_return; } if (is_member_of_groups(user_item, realm->groups) < 0) res = -1; authent_author_return: return res; } int good0, good1, good2; __attribute__ ((__noinline__, __noclone__)) char *foo(void) { asm (""); good0++; return ""; } __attribute__ ((__noinline__, __noclone__)) char *ha_get_string_value(void) { asm (""); good1++; return "f"; } __attribute__ ((__noinline__, __noclone__)) har has_auth_user(const char *a, const char *b, realm_type c, char *d, size_t e) { asm (""); if (*a != 'z' || a[1] != 0 || b != 0 || c != axis_realm || *d != 0 || e != 1) __builtin_abort (); return ha_no_error; } __attribute__ ((__noinline__, __noclone__)) har has_www_auth(char *a, size_t b, realm_type c, har d) { (void)(*a+b+c+d); asm (""); __builtin_abort (); } char *strdupped_user = "me"; __attribute__((__malloc__, __noclone__, __noinline__)) char* g_strdup (const char *str) { asm (""); if (*str != 'f') __builtin_abort (); good2++; return strdupped_user; } __attribute__((__noclone__, __noinline__)) void g_free (void * mem) { (void)mem; asm (""); __builtin_abort (); } struct user_info me = { .name = "me", .no_groups = 1, .groups = {42}, .next = 0}; struct user_info you = { .name = "you", .next = &me}; struct realm_group xgroups = { .name = "*", .id = 42, .next = 0}; int main(void) { char *orig_user = "?"; struct realm r = { .name = "x", .space = "space?", .groups = &xgroups, .next = 0}; request req = { .user = orig_user, .realm = "!", .authent = "z", .internal_realm = axis_realm}; realms = &r; users = &you; if (authent_author (&req) != 0 || good0 != 1 || good1 != 1 || good2 != 1 || req.user != orig_user || req.internal_realm != axis_realm) __builtin_abort (); __builtin_exit (0); }