1 /* { dg-do run } */
2 /* SEGV at comment below.  */
3 typedef unsigned int size_t;
4 typedef 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;
27 typedef enum realm_type
28 {
29   axis_realm = 0,
30   ws_realm
31 } realm_type;
32 
33 __attribute__((__noclone__, __noinline__))
34 har has_www_auth(char *, size_t, realm_type, har);
35 
36 __attribute__((__noclone__, __noinline__))
37 har has_auth_user(const char *, const char *, realm_type, char *, size_t);
38 
39 __attribute__((__noclone__, __noinline__))
40 char *ha_get_string_value(void);
41 
42 typedef struct
43 {
44   unsigned int track_id;
45   char* user;
46   char* realm;
47   char* authent;
48   int internal_realm;
49 } request;
50 enum 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 };
56 struct realm_group {
57   char *name;
58   int id;
59   struct realm_group *next;
60 };
61 struct realm {
62   char *name;
63   char *space;
64   struct realm_group *groups;
65   struct realm *next;
66 };
67 struct user_info {
68   char *name;
69   int no_groups;
70   int groups[128];
71   struct user_info *next;
72 };
73 static struct user_info *find_user(const char *user_name);
74 static int is_member_of_groups(const struct user_info *user_item,
75                                 const struct realm_group *groups);
76 int authent_author(request *req);
77 struct realm *realms = ((void *)0);
78 struct user_info *users = ((void *)0);
79 static struct user_info*
find_user(const char * user_name)80 find_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 }
92 static int
is_member_of_groups(const struct user_info * user_item,const struct realm_group * groups)93 is_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 }
107 char *foo (void) __attribute__((__noclone__, __noinline__));
108 char* g_strdup (const char *str) __attribute__((__malloc__, __noclone__, __noinline__));
109 int g_strcmp0 (const char *str1, const char *str2);
110 static int
is_basic(char ** user)111 is_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 }
122 static int
is_digest(char ** user)123 is_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__))
135 void g_free (void * mem);
136 static enum user_response
get_user_info_from_header(const realm_type type,char ** user_name,struct user_info ** user_item)137 get_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 }
161 static enum user_response
authenticate_user(request * req,char ** user_name,struct user_info ** user_item)162 authenticate_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 
189 int __attribute__ ((__noinline__, __noclone__))
authent_author(request * req)190 authent_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;
210 authent_author_return:
211   return res;
212 }
213 
214 int good0, good1, good2;
215 
216 __attribute__ ((__noinline__, __noclone__))
foo(void)217 char *foo(void)
218 {
219   asm ("");
220   good0++;
221   return "";
222 }
223 
224 __attribute__ ((__noinline__, __noclone__))
ha_get_string_value(void)225 char *ha_get_string_value(void)
226 {
227   asm ("");
228   good1++;
229   return "f";
230 }
231 
232 __attribute__ ((__noinline__, __noclone__))
has_auth_user(const char * a,const char * b,realm_type c,char * d,size_t e)233 har 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__))
has_www_auth(char * a,size_t b,realm_type c,har d)243 har 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 
251 char *strdupped_user = "me";
252 __attribute__((__malloc__, __noclone__, __noinline__))
g_strdup(const char * str)253 char* 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__))
g_free(void * mem)263 void g_free (void * mem)
264 {
265   (void)mem;
266   asm ("");
267   __builtin_abort ();
268 }
269 
270 struct user_info me = { .name = "me", .no_groups = 1, .groups = {42}, .next = 0};
271 struct user_info you = { .name = "you", .next = &me};
272 struct realm_group xgroups = { .name = "*", .id = 42, .next = 0};
273 
main(void)274 int 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