1/* { dg-do run } */
2/* SEGV at comment below.  */
3typedef unsigned int size_t;
4typedef enum har {
5  he_fatal = (-199),
6  he_not_initialized,
7  he_bad_input,
8  he_memory_too_small,
9  he_bad_action,
10  he_duplicate,
11  he_bad_nonce,
12  he_stale_nonce,
13  he_bad_credentials,
14  he_bad_user,
15  he_no_such_user,
16  he_bad_passwd,
17  he_unknown_auth_scheme,
18  he_not_found,
19  he_failed_digest_file_check,
20  he_failed_digest_file_save,
21  he_process_not_privileged,
22  he_other,
23  he_end_of_range,
24  ha_no_error = 0,
25  ha_no_value = 1
26} har;
27typedef enum realm_type
28{
29  axis_realm = 0,
30  ws_realm
31} realm_type;
32
33__attribute__((__noclone__, __noinline__))
34har has_www_auth(char *, size_t, realm_type, har);
35
36__attribute__((__noclone__, __noinline__))
37har has_auth_user(const char *, const char *, realm_type, char *, size_t);
38
39__attribute__((__noclone__, __noinline__))
40char *ha_get_string_value(void);
41
42typedef struct
43{
44  unsigned int track_id;
45  char* user;
46  char* realm;
47  char* authent;
48  int internal_realm;
49} request;
50enum user_response {
51  file_not_found_user_response = -3,
52  access_denied_user_response = -2,
53  no_user_response = -1,
54  ok_user_response = 0
55};
56struct realm_group {
57  char *name;
58  int id;
59  struct realm_group *next;
60};
61struct realm {
62  char *name;
63  char *space;
64  struct realm_group *groups;
65  struct realm *next;
66};
67struct user_info {
68  char *name;
69  int no_groups;
70  int groups[128];
71  struct user_info *next;
72};
73static struct user_info *find_user(const char *user_name);
74static int is_member_of_groups(const struct user_info *user_item,
75                                const struct realm_group *groups);
76int authent_author(request *req);
77struct realm *realms = ((void *)0);
78struct user_info *users = ((void *)0);
79static struct user_info*
80find_user(const char *user_name)
81{
82  struct user_info *user_item;
83  user_item = users;
84  while (user_item != ((void *)0)) {
85    /* SEGV due to NULL access here on user_name.  See also comment below.  */
86    if ((__builtin_strcmp(user_item->name, user_name) == 0))
87      break;
88    user_item = user_item->next;
89  }
90  return user_item;
91}
92static int
93is_member_of_groups(const struct user_info *user_item,
94                    const struct realm_group *groups)
95{
96  const struct realm_group *group_item;
97  int i;
98  group_item = groups;
99  while (group_item != ((void *)0)) {
100    for (i = 0; i < user_item->no_groups; i++)
101      if (user_item->groups[i] == group_item->id)
102	return 0;
103    group_item = group_item->next;
104  }
105  return -1;
106}
107char *foo (void) __attribute__((__noclone__, __noinline__));
108char* g_strdup (const char *str) __attribute__((__malloc__, __noclone__, __noinline__));
109int g_strcmp0 (const char *str1, const char *str2);
110static int
111is_basic(char **user)
112{
113  char *passwd_ptr;
114  char *authent = foo();
115  passwd_ptr = __builtin_strchr(authent, ':');
116  if (passwd_ptr != ((void *)0)) {
117    *user = g_strdup(authent);
118    return 0;
119  }
120  return -1;
121}
122static int
123is_digest(char **user)
124{
125  int ret_val = -1;
126  char *authent;
127  authent = ha_get_string_value();
128  if (authent) {
129    *user = g_strdup(authent);
130    ret_val = 0;
131  }
132  return ret_val;
133}
134__attribute__((__noclone__, __noinline__))
135void g_free (void * mem);
136static enum user_response
137get_user_info_from_header(const realm_type type,
138                          char **user_name,
139                          struct user_info **user_item)
140{
141  int ret_val = no_user_response;
142  if ((type == ws_realm)) {
143    if (is_basic(user_name) == 0)
144      ret_val = access_denied_user_response;
145    if (is_digest(user_name) == 0)
146      ret_val = ok_user_response;
147  } else {
148    if (is_basic(user_name) < 0 &&
149	/* Load of *user_name here, but not after the is_digest call.  */
150	is_digest(user_name) < 0)
151      ;
152    else if ((*user_item = find_user(*user_name)) != ((void *)0))
153      ret_val = ok_user_response;
154    else
155      ret_val = access_denied_user_response;
156    if (ret_val != ok_user_response)
157      g_free(*user_name);
158  }
159  return ret_val;
160}
161static enum user_response
162authenticate_user(request *req,
163                  char **user_name,
164                  struct user_info **user_item)
165{
166  char *authent = ((void *)0);
167  har resp = ha_no_value;
168  enum user_response user_resp;
169  int ret_val = no_user_response;
170  if (req->authent && __builtin_strlen(req->authent)) {
171    authent = req->authent;
172    user_resp = get_user_info_from_header(req->internal_realm,
173                                          user_name,
174                                          user_item);
175    if (user_resp == ok_user_response) {
176      resp = has_auth_user(authent, 0, req->internal_realm, "", 1);
177      if (resp == ha_no_error)
178	ret_val = ok_user_response;
179      else if (resp != he_stale_nonce)
180	ret_val = access_denied_user_response;
181    } else if (user_resp == access_denied_user_response)
182      ret_val = access_denied_user_response;
183  }
184  if (resp != he_memory_too_small && resp != ha_no_error)
185    resp = has_www_auth("", 1, req->internal_realm, resp);
186  return ret_val;
187}
188
189int __attribute__ ((__noinline__, __noclone__))
190authent_author(request *req)
191{
192  struct realm *realm;
193  char *user_name = ((void *)0);
194  struct user_info *user_item = ((void *)0);
195  int res = 0;
196  asm ("");
197  realm = realms;
198  if (__builtin_strcmp("Wsd", realm->name) == 0) {
199    req->internal_realm = ws_realm;
200    is_digest(&user_name);
201  }
202  if (authenticate_user(req, &user_name, &user_item) < 0) {
203    if (user_name != ((void *)0))
204      req->user = user_name;
205    res = -2;
206    goto authent_author_return;
207  }
208  if (is_member_of_groups(user_item, realm->groups) < 0)
209    res = -1;
210authent_author_return:
211  return res;
212}
213
214int good0, good1, good2;
215
216__attribute__ ((__noinline__, __noclone__))
217char *foo(void)
218{
219  asm ("");
220  good0++;
221  return "";
222}
223
224__attribute__ ((__noinline__, __noclone__))
225char *ha_get_string_value(void)
226{
227  asm ("");
228  good1++;
229  return "f";
230}
231
232__attribute__ ((__noinline__, __noclone__))
233har has_auth_user(const char *a, const char *b, realm_type c, char *d, size_t e)
234{
235  asm ("");
236  if (*a != 'z' || a[1] != 0 || b != 0 || c != axis_realm || *d != 0
237      || e != 1)
238    __builtin_abort ();
239  return ha_no_error;
240}
241
242__attribute__ ((__noinline__, __noclone__))
243har has_www_auth(char *a, size_t b, realm_type c, har d)
244{
245  (void)(*a+b+c+d);
246  asm ("");
247  __builtin_abort ();
248}
249
250
251char *strdupped_user = "me";
252__attribute__((__malloc__, __noclone__, __noinline__))
253char* g_strdup (const char *str)
254{
255  asm ("");
256  if (*str != 'f')
257    __builtin_abort ();
258  good2++;
259  return strdupped_user;
260}
261
262__attribute__((__noclone__, __noinline__))
263void g_free (void * mem)
264{
265  (void)mem;
266  asm ("");
267  __builtin_abort ();
268}
269
270struct user_info me = { .name = "me", .no_groups = 1, .groups = {42}, .next = 0};
271struct user_info you = { .name = "you", .next = &me};
272struct realm_group xgroups = { .name = "*", .id = 42, .next = 0};
273
274int main(void)
275{
276  char *orig_user = "?";
277  struct realm r = { .name = "x", .space = "space?", .groups = &xgroups, .next = 0};
278  request req = { .user = orig_user, .realm = "!", .authent = "z",
279		  .internal_realm = axis_realm};
280  realms = &r;
281  users = &you;
282  if (authent_author (&req) != 0 || good0 != 1 || good1 != 1 || good2 != 1
283      || req.user != orig_user
284      || req.internal_realm != axis_realm)
285    __builtin_abort ();
286  __builtin_exit (0);
287}
288
289