diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2018-05-28 05:21:55 -0400 |
---|---|---|
committer | Masahiro Yamada <yamada.masahiro@socionext.com> | 2018-05-28 14:31:19 -0400 |
commit | 915f64901eb3f1e4e126f58c0d2f82f5ec1d1223 (patch) | |
tree | ff55db36fc7f90bcc51af0070bc65ac947737c4d | |
parent | a702a6176e2fea9ae366a7345247eb886e4cc730 (diff) |
kconfig: error out if a recursive variable references itself
When using a recursively expanded variable, it is a common mistake
to make circular reference.
For example, Make terminates the following code:
X = $(X)
Y := $(X)
Let's detect the circular expansion in Kconfig, too.
On the other hand, a function that recurses itself is a commonly-used
programming technique. So, Make does not check recursion in the
reference with 'call'. For example, the following code continues
running eternally:
X = $(call X)
Y := $(X)
Kconfig allows circular expansion if one or more arguments are given,
but terminates when the same function is recursively invoked 1000 times,
assuming it is a programming mistake.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
-rw-r--r-- | scripts/kconfig/preprocess.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c index 0574039238c6..65da87fce907 100644 --- a/scripts/kconfig/preprocess.c +++ b/scripts/kconfig/preprocess.c | |||
@@ -229,6 +229,7 @@ struct variable { | |||
229 | char *name; | 229 | char *name; |
230 | char *value; | 230 | char *value; |
231 | enum variable_flavor flavor; | 231 | enum variable_flavor flavor; |
232 | int exp_count; | ||
232 | struct list_head node; | 233 | struct list_head node; |
233 | }; | 234 | }; |
234 | 235 | ||
@@ -253,11 +254,22 @@ static char *variable_expand(const char *name, int argc, char *argv[]) | |||
253 | if (!v) | 254 | if (!v) |
254 | return NULL; | 255 | return NULL; |
255 | 256 | ||
257 | if (argc == 0 && v->exp_count) | ||
258 | pperror("Recursive variable '%s' references itself (eventually)", | ||
259 | name); | ||
260 | |||
261 | if (v->exp_count > 1000) | ||
262 | pperror("Too deep recursive expansion"); | ||
263 | |||
264 | v->exp_count++; | ||
265 | |||
256 | if (v->flavor == VAR_RECURSIVE) | 266 | if (v->flavor == VAR_RECURSIVE) |
257 | res = expand_string_with_args(v->value, argc, argv); | 267 | res = expand_string_with_args(v->value, argc, argv); |
258 | else | 268 | else |
259 | res = xstrdup(v->value); | 269 | res = xstrdup(v->value); |
260 | 270 | ||
271 | v->exp_count--; | ||
272 | |||
261 | return res; | 273 | return res; |
262 | } | 274 | } |
263 | 275 | ||
@@ -284,6 +296,7 @@ void variable_add(const char *name, const char *value, | |||
284 | 296 | ||
285 | v = xmalloc(sizeof(*v)); | 297 | v = xmalloc(sizeof(*v)); |
286 | v->name = xstrdup(name); | 298 | v->name = xstrdup(name); |
299 | v->exp_count = 0; | ||
287 | list_add_tail(&v->node, &variable_list); | 300 | list_add_tail(&v->node, &variable_list); |
288 | } | 301 | } |
289 | 302 | ||