aboutsummaryrefslogtreecommitdiff
path: root/miscutils/make.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2024-10-20 14:23:43 +0100
committerRon Yorston <rmy@pobox.com>2024-10-20 14:23:43 +0100
commitf0dea66749bb599f65762991f4fded229c3df5a3 (patch)
treead729d6f48445907f97e1197d4cf8392e684b5e3 /miscutils/make.c
parentef4756eb0994bc25de66cbb04e1752dda217ff5d (diff)
downloadbusybox-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.c54
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
388static void 388static void
389error_not_allowed(const char *s, const char *t)
390{
391 error("%s not allowed for %s", s, t);
392}
393
394static void
389warning(const char *msg, ...) 395warning(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 1812enum {
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