Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

genksyms: Fix enum consts from a reference affecting new values

Enumeration constants read from a symbol reference file can incorrectly
affect new enumeration constants parsed from an actual input file.

Example:

$ cat test.c
enum { E_A, E_B, E_MAX };
struct bar { int mem[E_MAX]; };
int foo(struct bar *a) {}
__GENKSYMS_EXPORT_SYMBOL(foo);

$ cat test.c | ./scripts/genksyms/genksyms -T test.0.symtypes
#SYMVER foo 0x070d854d

$ cat test.0.symtypes
E#E_MAX 2
s#bar struct bar { int mem [ E#E_MAX ] ; }
foo int foo ( s#bar * )

$ cat test.c | ./scripts/genksyms/genksyms -T test.1.symtypes -r test.0.symtypes
<stdin>:4: warning: foo: modversion changed because of changes in enum constant E_MAX
#SYMVER foo 0x9c9dfd81

$ cat test.1.symtypes
E#E_MAX ( 2 ) + 3
s#bar struct bar { int mem [ E#E_MAX ] ; }
foo int foo ( s#bar * )

The __add_symbol() function includes logic to handle the incrementation of
enumeration values, but this code is also invoked when reading a reference
file. As a result, the variables last_enum_expr and enum_counter might be
incorrectly set after reading the reference file, which later affects
parsing of the actual input.

Fix the problem by splitting the logic for the incrementation of
enumeration values into a separate function process_enum() and call it from
__add_symbol() only when processing non-reference data.

Fixes: e37ddb825003 ("genksyms: Track changes to enum constants")
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>

authored by

Petr Pavlu and committed by
Masahiro Yamada
c50a04f8 e21efe83

+20 -7
+20 -7
scripts/genksyms/genksyms.c
··· 181 181 strcmp(defn->string, "{") == 0); 182 182 } 183 183 184 - static struct symbol *__add_symbol(const char *name, enum symbol_type type, 185 - struct string_list *defn, int is_extern, 186 - int is_reference) 184 + static struct string_list *process_enum(const char *name, enum symbol_type type, 185 + struct string_list *defn) 187 186 { 188 - unsigned long h; 189 - struct symbol *sym; 190 - enum symbol_status status = STATUS_UNCHANGED; 191 187 /* The parser adds symbols in the order their declaration completes, 192 188 * so it is safe to store the value of the previous enum constant in 193 189 * a static variable. ··· 212 216 defn = mk_node(buf); 213 217 } 214 218 } 215 - } else if (type == SYM_ENUM) { 219 + } else { 216 220 free_list(last_enum_expr, NULL); 217 221 last_enum_expr = NULL; 218 222 enum_counter = 0; 219 223 if (!name) 220 224 /* Anonymous enum definition, nothing more to do */ 225 + return NULL; 226 + } 227 + 228 + return defn; 229 + } 230 + 231 + static struct symbol *__add_symbol(const char *name, enum symbol_type type, 232 + struct string_list *defn, int is_extern, 233 + int is_reference) 234 + { 235 + unsigned long h; 236 + struct symbol *sym; 237 + enum symbol_status status = STATUS_UNCHANGED; 238 + 239 + if ((type == SYM_ENUM_CONST || type == SYM_ENUM) && !is_reference) { 240 + defn = process_enum(name, type, defn); 241 + if (defn == NULL) 221 242 return NULL; 222 243 } 223 244