diff options
author | Ron Yorston <rmy@pobox.com> | 2024-10-20 14:23:43 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2024-10-20 14:23:43 +0100 |
commit | f0dea66749bb599f65762991f4fded229c3df5a3 (patch) | |
tree | ad729d6f48445907f97e1197d4cf8392e684b5e3 /miscutils/make.c | |
parent | ef4756eb0994bc25de66cbb04e1752dda217ff5d (diff) | |
download | busybox-w32-f0dea66749bb599f65762991f4fded229c3df5a3.tar.gz busybox-w32-f0dea66749bb599f65762991f4fded229c3df5a3.tar.bz2 busybox-w32-f0dea66749bb599f65762991f4fded229c3df5a3.zip |
make: enforce restrictions on prerequisites/commands
POSIX mentions some restrictions on whether rules may or may not
have prerequisites or commands:
- most special targets shouldn't have commnds;
- inference/.DEFAULT rules shouldn't have prerequisites.
Enforce these restrictions in POSIX mode.
Generally, implementations are happy to accept prerequisites or
commands even if they're subsequently ignored. Allow this as an
extension.
Adds 216-256 bytes.
Diffstat (limited to 'miscutils/make.c')
-rw-r--r-- | miscutils/make.c | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/miscutils/make.c b/miscutils/make.c index df810677f..bf1cfe226 100644 --- a/miscutils/make.c +++ b/miscutils/make.c | |||
@@ -386,6 +386,12 @@ error_in_inference_rule(const char *s) | |||
386 | } | 386 | } |
387 | 387 | ||
388 | static void | 388 | static void |
389 | error_not_allowed(const char *s, const char *t) | ||
390 | { | ||
391 | error("%s not allowed for %s", s, t); | ||
392 | } | ||
393 | |||
394 | static void | ||
389 | warning(const char *msg, ...) | 395 | warning(const char *msg, ...) |
390 | { | 396 | { |
391 | va_list list; | 397 | va_list list; |
@@ -1803,9 +1809,14 @@ is_suffix(const char *s) | |||
1803 | return FALSE; | 1809 | return FALSE; |
1804 | } | 1810 | } |
1805 | 1811 | ||
1806 | #define T_NORMAL 0 | 1812 | enum { |
1807 | #define T_SPECIAL 1 | 1813 | T_NORMAL = 0, |
1808 | #define T_INFERENCE 2 | 1814 | T_SPECIAL = (1 << 0), |
1815 | T_INFERENCE = (1 << 1), // Inference rule | ||
1816 | T_NOPREREQ = (1 << 2), // If set must not have prerequisites | ||
1817 | T_COMMAND = (1 << 3), // If set must have commands, if unset must not | ||
1818 | }; | ||
1819 | |||
1809 | /* | 1820 | /* |
1810 | * Determine if the argument is a special target and return a set | 1821 | * Determine if the argument is a special target and return a set |
1811 | * of flags indicating its properties. | 1822 | * of flags indicating its properties. |
@@ -1830,24 +1841,38 @@ target_type(char *s) | |||
1830 | #endif | 1841 | #endif |
1831 | ; | 1842 | ; |
1832 | 1843 | ||
1844 | static const uint8_t s_type[] = { | ||
1845 | T_SPECIAL | T_NOPREREQ | T_COMMAND, | ||
1846 | T_SPECIAL | T_NOPREREQ, | ||
1847 | T_SPECIAL, | ||
1848 | T_SPECIAL, | ||
1849 | T_SPECIAL, | ||
1850 | T_SPECIAL, | ||
1851 | T_SPECIAL, | ||
1852 | T_SPECIAL | T_NOPREREQ, | ||
1853 | T_SPECIAL, | ||
1854 | T_SPECIAL, | ||
1855 | }; | ||
1856 | |||
1833 | if (*s != '.') | 1857 | if (*s != '.') |
1834 | return T_NORMAL; | 1858 | return T_NORMAL; |
1835 | 1859 | ||
1836 | // Check for one of the known special targets | 1860 | // Check for one of the known special targets |
1837 | if (index_in_strings(s_name, s) >= 0) | 1861 | ret = index_in_strings(s_name, s); |
1838 | return T_SPECIAL; | 1862 | if (ret >= 0) |
1863 | return s_type[ret]; | ||
1839 | 1864 | ||
1840 | // Check for an inference rule | 1865 | // Check for an inference rule |
1841 | ret = T_NORMAL; | 1866 | ret = T_NORMAL; |
1842 | sfx = suffix(s); | 1867 | sfx = suffix(s); |
1843 | if (is_suffix(sfx)) { | 1868 | if (is_suffix(sfx)) { |
1844 | if (s == sfx) { // Single suffix rule | 1869 | if (s == sfx) { // Single suffix rule |
1845 | ret = T_INFERENCE; | 1870 | ret = T_INFERENCE | T_NOPREREQ | T_COMMAND; |
1846 | } else { | 1871 | } else { |
1847 | // Suffix is valid, check that prefix is too | 1872 | // Suffix is valid, check that prefix is too |
1848 | *sfx = '\0'; | 1873 | *sfx = '\0'; |
1849 | if (is_suffix(s)) | 1874 | if (is_suffix(s)) |
1850 | ret = T_INFERENCE; | 1875 | ret = T_INFERENCE | T_NOPREREQ | T_COMMAND; |
1851 | *sfx = '.'; | 1876 | *sfx = '.'; |
1852 | } | 1877 | } |
1853 | } | 1878 | } |
@@ -2347,12 +2372,23 @@ input(FILE *fd, int ilevel) | |||
2347 | 2372 | ||
2348 | np = newname(files[i]); | 2373 | np = newname(files[i]); |
2349 | if (ttype != T_NORMAL) { | 2374 | if (ttype != T_NORMAL) { |
2350 | if (ttype == T_INFERENCE) { | 2375 | // Enforce prerequisites/commands in POSIX mode |
2351 | if (posix) { | 2376 | if (posix) { |
2377 | if ((ttype & T_NOPREREQ) && dp) | ||
2378 | error_not_allowed("prerequisites", p); | ||
2379 | if ((ttype & T_INFERENCE)) { | ||
2352 | if (semicolon_cmd) | 2380 | if (semicolon_cmd) |
2353 | error_in_inference_rule("'; command'"); | 2381 | error_in_inference_rule("'; command'"); |
2354 | seen_inference = TRUE; | 2382 | seen_inference = TRUE; |
2355 | } | 2383 | } |
2384 | if ((ttype & T_COMMAND) && !cp && | ||
2385 | !((ttype & T_INFERENCE) && !semicolon_cmd)) | ||
2386 | error("commands required for %s", p); | ||
2387 | if (!(ttype & T_COMMAND) && cp) | ||
2388 | error_not_allowed("commands", p); | ||
2389 | } | ||
2390 | |||
2391 | if ((ttype & T_INFERENCE)) { | ||
2356 | np->n_flag |= N_INFERENCE; | 2392 | np->n_flag |= N_INFERENCE; |
2357 | } else if (strcmp(p, ".DEFAULT") == 0) { | 2393 | } else if (strcmp(p, ".DEFAULT") == 0) { |
2358 | // .DEFAULT rule is a special case | 2394 | // .DEFAULT rule is a special case |