xref: /aosp_15_r20/external/AFLplusplus/include/list.h (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1*08b48e0bSAndroid Build Coastguard Worker /*
2*08b48e0bSAndroid Build Coastguard Worker    american fuzzy lop++ - linked list code
3*08b48e0bSAndroid Build Coastguard Worker    ---------------------------------------
4*08b48e0bSAndroid Build Coastguard Worker 
5*08b48e0bSAndroid Build Coastguard Worker    Originally written by Michal Zalewski
6*08b48e0bSAndroid Build Coastguard Worker 
7*08b48e0bSAndroid Build Coastguard Worker    Now maintained by Marc Heuse <[email protected]>,
8*08b48e0bSAndroid Build Coastguard Worker                      Heiko Eißfeldt <[email protected]>,
9*08b48e0bSAndroid Build Coastguard Worker                      Andrea Fioraldi <[email protected]>,
10*08b48e0bSAndroid Build Coastguard Worker                      Dominik Maier <[email protected]>
11*08b48e0bSAndroid Build Coastguard Worker 
12*08b48e0bSAndroid Build Coastguard Worker    Copyright 2016, 2017 Google Inc. All rights reserved.
13*08b48e0bSAndroid Build Coastguard Worker    Copyright 2019-2024 AFLplusplus Project. All rights reserved.
14*08b48e0bSAndroid Build Coastguard Worker 
15*08b48e0bSAndroid Build Coastguard Worker    Licensed under the Apache License, Version 2.0 (the "License");
16*08b48e0bSAndroid Build Coastguard Worker    you may not use this file except in compliance with the License.
17*08b48e0bSAndroid Build Coastguard Worker    You may obtain a copy of the License at:
18*08b48e0bSAndroid Build Coastguard Worker 
19*08b48e0bSAndroid Build Coastguard Worker      https://www.apache.org/licenses/LICENSE-2.0
20*08b48e0bSAndroid Build Coastguard Worker 
21*08b48e0bSAndroid Build Coastguard Worker    This allocator is not designed to resist malicious attackers (the canaries
22*08b48e0bSAndroid Build Coastguard Worker    are small and predictable), but provides a robust and portable way to detect
23*08b48e0bSAndroid Build Coastguard Worker    use-after-free, off-by-one writes, stale pointers, and so on.
24*08b48e0bSAndroid Build Coastguard Worker 
25*08b48e0bSAndroid Build Coastguard Worker  */
26*08b48e0bSAndroid Build Coastguard Worker 
27*08b48e0bSAndroid Build Coastguard Worker #ifndef AFL_LIST
28*08b48e0bSAndroid Build Coastguard Worker #define AFL_LIST
29*08b48e0bSAndroid Build Coastguard Worker 
30*08b48e0bSAndroid Build Coastguard Worker #include <stdio.h>
31*08b48e0bSAndroid Build Coastguard Worker #include <stdbool.h>
32*08b48e0bSAndroid Build Coastguard Worker #include <string.h>
33*08b48e0bSAndroid Build Coastguard Worker 
34*08b48e0bSAndroid Build Coastguard Worker #include "debug.h"
35*08b48e0bSAndroid Build Coastguard Worker #include "afl-prealloc.h"
36*08b48e0bSAndroid Build Coastguard Worker 
37*08b48e0bSAndroid Build Coastguard Worker /* How many elements to allocate before malloc is needed */
38*08b48e0bSAndroid Build Coastguard Worker #define LIST_PREALLOC_SIZE (64)
39*08b48e0bSAndroid Build Coastguard Worker 
40*08b48e0bSAndroid Build Coastguard Worker typedef struct list_element {
41*08b48e0bSAndroid Build Coastguard Worker 
42*08b48e0bSAndroid Build Coastguard Worker   PREALLOCABLE;
43*08b48e0bSAndroid Build Coastguard Worker 
44*08b48e0bSAndroid Build Coastguard Worker   struct list_element *prev;
45*08b48e0bSAndroid Build Coastguard Worker   struct list_element *next;
46*08b48e0bSAndroid Build Coastguard Worker   void                *data;
47*08b48e0bSAndroid Build Coastguard Worker 
48*08b48e0bSAndroid Build Coastguard Worker } element_t;
49*08b48e0bSAndroid Build Coastguard Worker 
50*08b48e0bSAndroid Build Coastguard Worker typedef struct list {
51*08b48e0bSAndroid Build Coastguard Worker 
52*08b48e0bSAndroid Build Coastguard Worker   element_t element_prealloc_buf[LIST_PREALLOC_SIZE];
53*08b48e0bSAndroid Build Coastguard Worker   s32       element_prealloc_count;
54*08b48e0bSAndroid Build Coastguard Worker 
55*08b48e0bSAndroid Build Coastguard Worker } list_t;
56*08b48e0bSAndroid Build Coastguard Worker 
get_head(list_t * list)57*08b48e0bSAndroid Build Coastguard Worker static inline element_t *get_head(list_t *list) {
58*08b48e0bSAndroid Build Coastguard Worker 
59*08b48e0bSAndroid Build Coastguard Worker   /* The first element is the head */
60*08b48e0bSAndroid Build Coastguard Worker   return list->element_prealloc_buf;
61*08b48e0bSAndroid Build Coastguard Worker 
62*08b48e0bSAndroid Build Coastguard Worker }
63*08b48e0bSAndroid Build Coastguard Worker 
list_free_el(list_t * list,element_t * el)64*08b48e0bSAndroid Build Coastguard Worker static inline void list_free_el(list_t *list, element_t *el) {
65*08b48e0bSAndroid Build Coastguard Worker 
66*08b48e0bSAndroid Build Coastguard Worker   PRE_FREE(el, list->element_prealloc_count);
67*08b48e0bSAndroid Build Coastguard Worker 
68*08b48e0bSAndroid Build Coastguard Worker }
69*08b48e0bSAndroid Build Coastguard Worker 
list_append(list_t * list,void * el)70*08b48e0bSAndroid Build Coastguard Worker static inline void list_append(list_t *list, void *el) {
71*08b48e0bSAndroid Build Coastguard Worker 
72*08b48e0bSAndroid Build Coastguard Worker   element_t *head = get_head(list);
73*08b48e0bSAndroid Build Coastguard Worker   if (!head->next) {
74*08b48e0bSAndroid Build Coastguard Worker 
75*08b48e0bSAndroid Build Coastguard Worker     /* initialize */
76*08b48e0bSAndroid Build Coastguard Worker 
77*08b48e0bSAndroid Build Coastguard Worker     memset(list, 0, sizeof(list_t));
78*08b48e0bSAndroid Build Coastguard Worker     PRE_ALLOC_FORCE(head, list->element_prealloc_count);
79*08b48e0bSAndroid Build Coastguard Worker     head->next = head->prev = head;
80*08b48e0bSAndroid Build Coastguard Worker 
81*08b48e0bSAndroid Build Coastguard Worker   }
82*08b48e0bSAndroid Build Coastguard Worker 
83*08b48e0bSAndroid Build Coastguard Worker   element_t *el_box = NULL;
84*08b48e0bSAndroid Build Coastguard Worker 
85*08b48e0bSAndroid Build Coastguard Worker   PRE_ALLOC(el_box, list->element_prealloc_buf, LIST_PREALLOC_SIZE,
86*08b48e0bSAndroid Build Coastguard Worker             list->element_prealloc_count);
87*08b48e0bSAndroid Build Coastguard Worker   if (!el_box) { FATAL("failed to allocate list element"); }
88*08b48e0bSAndroid Build Coastguard Worker   el_box->data = el;
89*08b48e0bSAndroid Build Coastguard Worker   el_box->next = head;
90*08b48e0bSAndroid Build Coastguard Worker   el_box->prev = head->prev;
91*08b48e0bSAndroid Build Coastguard Worker   head->prev->next = el_box;
92*08b48e0bSAndroid Build Coastguard Worker   head->prev = el_box;
93*08b48e0bSAndroid Build Coastguard Worker 
94*08b48e0bSAndroid Build Coastguard Worker }
95*08b48e0bSAndroid Build Coastguard Worker 
96*08b48e0bSAndroid Build Coastguard Worker /* Simple foreach.
97*08b48e0bSAndroid Build Coastguard Worker    Pointer to the current element is in `el`,
98*08b48e0bSAndroid Build Coastguard Worker    casted to (a pointer) of the given `type`.
99*08b48e0bSAndroid Build Coastguard Worker    A return from this block will return from calling func.
100*08b48e0bSAndroid Build Coastguard Worker */
101*08b48e0bSAndroid Build Coastguard Worker 
102*08b48e0bSAndroid Build Coastguard Worker #define LIST_FOREACH(list, type, block)                            \
103*08b48e0bSAndroid Build Coastguard Worker   do {                                                             \
104*08b48e0bSAndroid Build Coastguard Worker                                                                    \
105*08b48e0bSAndroid Build Coastguard Worker     list_t    *li = (list);                                        \
106*08b48e0bSAndroid Build Coastguard Worker     element_t *head = get_head((li));                              \
107*08b48e0bSAndroid Build Coastguard Worker     element_t *el_box = (head)->next;                              \
108*08b48e0bSAndroid Build Coastguard Worker     if (!el_box) FATAL("foreach over uninitialized list");         \
109*08b48e0bSAndroid Build Coastguard Worker     while (el_box != head) {                                       \
110*08b48e0bSAndroid Build Coastguard Worker                                                                    \
111*08b48e0bSAndroid Build Coastguard Worker       __attribute__((unused)) type *el = (type *)((el_box)->data); \
112*08b48e0bSAndroid Build Coastguard Worker       /* get next so el_box can be unlinked */                     \
113*08b48e0bSAndroid Build Coastguard Worker       element_t *next = el_box->next;                              \
114*08b48e0bSAndroid Build Coastguard Worker       {block};                                                     \
115*08b48e0bSAndroid Build Coastguard Worker       el_box = next;                                               \
116*08b48e0bSAndroid Build Coastguard Worker                                                                    \
117*08b48e0bSAndroid Build Coastguard Worker     }                                                              \
118*08b48e0bSAndroid Build Coastguard Worker                                                                    \
119*08b48e0bSAndroid Build Coastguard Worker   } while (0);
120*08b48e0bSAndroid Build Coastguard Worker 
121*08b48e0bSAndroid Build Coastguard Worker /* In foreach: remove the current el from the list */
122*08b48e0bSAndroid Build Coastguard Worker 
123*08b48e0bSAndroid Build Coastguard Worker #define LIST_REMOVE_CURRENT_EL_IN_FOREACH() \
124*08b48e0bSAndroid Build Coastguard Worker   do {                                      \
125*08b48e0bSAndroid Build Coastguard Worker                                             \
126*08b48e0bSAndroid Build Coastguard Worker     el_box->prev->next = next;              \
127*08b48e0bSAndroid Build Coastguard Worker     el_box->next->prev = el_box->prev;      \
128*08b48e0bSAndroid Build Coastguard Worker     list_free_el(li, el_box);               \
129*08b48e0bSAndroid Build Coastguard Worker                                             \
130*08b48e0bSAndroid Build Coastguard Worker   } while (0);
131*08b48e0bSAndroid Build Coastguard Worker 
132*08b48e0bSAndroid Build Coastguard Worker /* Same as foreach, but will clear list in the process */
133*08b48e0bSAndroid Build Coastguard Worker 
134*08b48e0bSAndroid Build Coastguard Worker #define LIST_FOREACH_CLEAR(list, type, block) \
135*08b48e0bSAndroid Build Coastguard Worker   do {                                        \
136*08b48e0bSAndroid Build Coastguard Worker                                               \
137*08b48e0bSAndroid Build Coastguard Worker     LIST_FOREACH((list), type, {              \
138*08b48e0bSAndroid Build Coastguard Worker                                               \
139*08b48e0bSAndroid Build Coastguard Worker       {block};                                \
140*08b48e0bSAndroid Build Coastguard Worker       LIST_REMOVE_CURRENT_EL_IN_FOREACH();    \
141*08b48e0bSAndroid Build Coastguard Worker                                               \
142*08b48e0bSAndroid Build Coastguard Worker     });                                       \
143*08b48e0bSAndroid Build Coastguard Worker                                               \
144*08b48e0bSAndroid Build Coastguard Worker   } while (0);
145*08b48e0bSAndroid Build Coastguard Worker 
146*08b48e0bSAndroid Build Coastguard Worker /* remove an item from the list */
147*08b48e0bSAndroid Build Coastguard Worker 
list_remove(list_t * list,void * remove_me)148*08b48e0bSAndroid Build Coastguard Worker static inline void list_remove(list_t *list, void *remove_me) {
149*08b48e0bSAndroid Build Coastguard Worker 
150*08b48e0bSAndroid Build Coastguard Worker   LIST_FOREACH(list, void, {
151*08b48e0bSAndroid Build Coastguard Worker 
152*08b48e0bSAndroid Build Coastguard Worker     if (el == remove_me) {
153*08b48e0bSAndroid Build Coastguard Worker 
154*08b48e0bSAndroid Build Coastguard Worker       el_box->prev->next = el_box->next;
155*08b48e0bSAndroid Build Coastguard Worker       el_box->next->prev = el_box->prev;
156*08b48e0bSAndroid Build Coastguard Worker       el_box->data = NULL;
157*08b48e0bSAndroid Build Coastguard Worker       list_free_el(list, el_box);
158*08b48e0bSAndroid Build Coastguard Worker       return;
159*08b48e0bSAndroid Build Coastguard Worker 
160*08b48e0bSAndroid Build Coastguard Worker     }
161*08b48e0bSAndroid Build Coastguard Worker 
162*08b48e0bSAndroid Build Coastguard Worker   });
163*08b48e0bSAndroid Build Coastguard Worker 
164*08b48e0bSAndroid Build Coastguard Worker   FATAL("List item to be removed not in list");
165*08b48e0bSAndroid Build Coastguard Worker 
166*08b48e0bSAndroid Build Coastguard Worker }
167*08b48e0bSAndroid Build Coastguard Worker 
168*08b48e0bSAndroid Build Coastguard Worker /* Returns true if el is in list */
169*08b48e0bSAndroid Build Coastguard Worker 
list_contains(list_t * list,void * contains_me)170*08b48e0bSAndroid Build Coastguard Worker static inline bool list_contains(list_t *list, void *contains_me) {
171*08b48e0bSAndroid Build Coastguard Worker 
172*08b48e0bSAndroid Build Coastguard Worker   LIST_FOREACH(list, void, {
173*08b48e0bSAndroid Build Coastguard Worker 
174*08b48e0bSAndroid Build Coastguard Worker     if (el == contains_me) return true;
175*08b48e0bSAndroid Build Coastguard Worker 
176*08b48e0bSAndroid Build Coastguard Worker   });
177*08b48e0bSAndroid Build Coastguard Worker 
178*08b48e0bSAndroid Build Coastguard Worker   return false;
179*08b48e0bSAndroid Build Coastguard Worker 
180*08b48e0bSAndroid Build Coastguard Worker }
181*08b48e0bSAndroid Build Coastguard Worker 
182*08b48e0bSAndroid Build Coastguard Worker #endif
183*08b48e0bSAndroid Build Coastguard Worker 
184