0004-add-fallback-parse_printf_format-implementation.patch 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. From 3d9910dcda697b1e361bba49c99050ee0d116742 Mon Sep 17 00:00:00 2001
  2. From: Alexander Kanavin <alex.kanavin@gmail.com>
  3. Date: Sat, 22 May 2021 20:26:24 +0200
  4. Subject: [PATCH] add fallback parse_printf_format implementation
  5. Upstream-Status: Inappropriate [musl specific]
  6. Signed-off-by: Emil Renner Berthing <systemd@esmil.dk>
  7. Signed-off-by: Khem Raj <raj.khem@gmail.com>
  8. Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
  9. [rebased for systemd 243]
  10. Signed-off-by: Scott Murray <scott.murray@konsulko.com>
  11. ---
  12. meson.build | 1 +
  13. src/basic/meson.build | 5 +
  14. src/basic/parse-printf-format.c | 273 +++++++++++++++++++++++
  15. src/basic/parse-printf-format.h | 57 +++++
  16. src/basic/stdio-util.h | 2 +-
  17. src/libsystemd/sd-journal/journal-send.c | 2 +-
  18. 6 files changed, 338 insertions(+), 2 deletions(-)
  19. create mode 100644 src/basic/parse-printf-format.c
  20. create mode 100644 src/basic/parse-printf-format.h
  21. --- a/meson.build
  22. +++ b/meson.build
  23. @@ -739,6 +739,7 @@ endif
  24. foreach header : ['crypt.h',
  25. 'linux/memfd.h',
  26. 'linux/vm_sockets.h',
  27. + 'printf.h',
  28. 'sys/auxv.h',
  29. 'valgrind/memcheck.h',
  30. 'valgrind/valgrind.h',
  31. --- a/src/basic/meson.build
  32. +++ b/src/basic/meson.build
  33. @@ -337,6 +337,11 @@ endforeach
  34. basic_sources += generated_gperf_headers
  35. +if conf.get('HAVE_PRINTF_H') != 1
  36. + basic_sources += [files('parse-printf-format.c')]
  37. +endif
  38. +
  39. +
  40. ############################################################
  41. arch_list = [
  42. --- /dev/null
  43. +++ b/src/basic/parse-printf-format.c
  44. @@ -0,0 +1,273 @@
  45. +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
  46. +
  47. +/***
  48. + This file is part of systemd.
  49. +
  50. + Copyright 2014 Emil Renner Berthing <systemd@esmil.dk>
  51. +
  52. + With parts from the musl C library
  53. + Copyright 2005-2014 Rich Felker, et al.
  54. +
  55. + systemd is free software; you can redistribute it and/or modify it
  56. + under the terms of the GNU Lesser General Public License as published by
  57. + the Free Software Foundation; either version 2.1 of the License, or
  58. + (at your option) any later version.
  59. +
  60. + systemd is distributed in the hope that it will be useful, but
  61. + WITHOUT ANY WARRANTY; without even the implied warranty of
  62. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  63. + Lesser General Public License for more details.
  64. +
  65. + You should have received a copy of the GNU Lesser General Public License
  66. + along with systemd; If not, see <http://www.gnu.org/licenses/>.
  67. +***/
  68. +
  69. +#include <stddef.h>
  70. +#include <string.h>
  71. +
  72. +#include "parse-printf-format.h"
  73. +
  74. +static const char *consume_nonarg(const char *fmt)
  75. +{
  76. + do {
  77. + if (*fmt == '\0')
  78. + return fmt;
  79. + } while (*fmt++ != '%');
  80. + return fmt;
  81. +}
  82. +
  83. +static const char *consume_num(const char *fmt)
  84. +{
  85. + for (;*fmt >= '0' && *fmt <= '9'; fmt++)
  86. + /* do nothing */;
  87. + return fmt;
  88. +}
  89. +
  90. +static const char *consume_argn(const char *fmt, size_t *arg)
  91. +{
  92. + const char *p = fmt;
  93. + size_t val = 0;
  94. +
  95. + if (*p < '1' || *p > '9')
  96. + return fmt;
  97. + do {
  98. + val = 10*val + (*p++ - '0');
  99. + } while (*p >= '0' && *p <= '9');
  100. +
  101. + if (*p != '$')
  102. + return fmt;
  103. + *arg = val;
  104. + return p+1;
  105. +}
  106. +
  107. +static const char *consume_flags(const char *fmt)
  108. +{
  109. + while (1) {
  110. + switch (*fmt) {
  111. + case '#':
  112. + case '0':
  113. + case '-':
  114. + case ' ':
  115. + case '+':
  116. + case '\'':
  117. + case 'I':
  118. + fmt++;
  119. + continue;
  120. + }
  121. + return fmt;
  122. + }
  123. +}
  124. +
  125. +enum state {
  126. + BARE,
  127. + LPRE,
  128. + LLPRE,
  129. + HPRE,
  130. + HHPRE,
  131. + BIGLPRE,
  132. + ZTPRE,
  133. + JPRE,
  134. + STOP
  135. +};
  136. +
  137. +enum type {
  138. + NONE,
  139. + PTR,
  140. + INT,
  141. + UINT,
  142. + ULLONG,
  143. + LONG,
  144. + ULONG,
  145. + SHORT,
  146. + USHORT,
  147. + CHAR,
  148. + UCHAR,
  149. + LLONG,
  150. + SIZET,
  151. + IMAX,
  152. + UMAX,
  153. + PDIFF,
  154. + UIPTR,
  155. + DBL,
  156. + LDBL,
  157. + MAXTYPE
  158. +};
  159. +
  160. +static const short pa_types[MAXTYPE] = {
  161. + [NONE] = PA_INT,
  162. + [PTR] = PA_POINTER,
  163. + [INT] = PA_INT,
  164. + [UINT] = PA_INT,
  165. + [ULLONG] = PA_INT | PA_FLAG_LONG_LONG,
  166. + [LONG] = PA_INT | PA_FLAG_LONG,
  167. + [ULONG] = PA_INT | PA_FLAG_LONG,
  168. + [SHORT] = PA_INT | PA_FLAG_SHORT,
  169. + [USHORT] = PA_INT | PA_FLAG_SHORT,
  170. + [CHAR] = PA_CHAR,
  171. + [UCHAR] = PA_CHAR,
  172. + [LLONG] = PA_INT | PA_FLAG_LONG_LONG,
  173. + [SIZET] = PA_INT | PA_FLAG_LONG,
  174. + [IMAX] = PA_INT | PA_FLAG_LONG_LONG,
  175. + [UMAX] = PA_INT | PA_FLAG_LONG_LONG,
  176. + [PDIFF] = PA_INT | PA_FLAG_LONG_LONG,
  177. + [UIPTR] = PA_INT | PA_FLAG_LONG,
  178. + [DBL] = PA_DOUBLE,
  179. + [LDBL] = PA_DOUBLE | PA_FLAG_LONG_DOUBLE
  180. +};
  181. +
  182. +#define S(x) [(x)-'A']
  183. +#define E(x) (STOP + (x))
  184. +
  185. +static const unsigned char states[]['z'-'A'+1] = {
  186. + { /* 0: bare types */
  187. + S('d') = E(INT), S('i') = E(INT),
  188. + S('o') = E(UINT),S('u') = E(UINT),S('x') = E(UINT), S('X') = E(UINT),
  189. + S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
  190. + S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
  191. + S('c') = E(CHAR),S('C') = E(INT),
  192. + S('s') = E(PTR), S('S') = E(PTR), S('p') = E(UIPTR),S('n') = E(PTR),
  193. + S('m') = E(NONE),
  194. + S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
  195. + S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE
  196. + }, { /* 1: l-prefixed */
  197. + S('d') = E(LONG), S('i') = E(LONG),
  198. + S('o') = E(ULONG),S('u') = E(ULONG),S('x') = E(ULONG),S('X') = E(ULONG),
  199. + S('e') = E(DBL), S('f') = E(DBL), S('g') = E(DBL), S('a') = E(DBL),
  200. + S('E') = E(DBL), S('F') = E(DBL), S('G') = E(DBL), S('A') = E(DBL),
  201. + S('c') = E(INT), S('s') = E(PTR), S('n') = E(PTR),
  202. + S('l') = LLPRE
  203. + }, { /* 2: ll-prefixed */
  204. + S('d') = E(LLONG), S('i') = E(LLONG),
  205. + S('o') = E(ULLONG),S('u') = E(ULLONG),
  206. + S('x') = E(ULLONG),S('X') = E(ULLONG),
  207. + S('n') = E(PTR)
  208. + }, { /* 3: h-prefixed */
  209. + S('d') = E(SHORT), S('i') = E(SHORT),
  210. + S('o') = E(USHORT),S('u') = E(USHORT),
  211. + S('x') = E(USHORT),S('X') = E(USHORT),
  212. + S('n') = E(PTR),
  213. + S('h') = HHPRE
  214. + }, { /* 4: hh-prefixed */
  215. + S('d') = E(CHAR), S('i') = E(CHAR),
  216. + S('o') = E(UCHAR),S('u') = E(UCHAR),
  217. + S('x') = E(UCHAR),S('X') = E(UCHAR),
  218. + S('n') = E(PTR)
  219. + }, { /* 5: L-prefixed */
  220. + S('e') = E(LDBL),S('f') = E(LDBL),S('g') = E(LDBL), S('a') = E(LDBL),
  221. + S('E') = E(LDBL),S('F') = E(LDBL),S('G') = E(LDBL), S('A') = E(LDBL),
  222. + S('n') = E(PTR)
  223. + }, { /* 6: z- or t-prefixed (assumed to be same size) */
  224. + S('d') = E(PDIFF),S('i') = E(PDIFF),
  225. + S('o') = E(SIZET),S('u') = E(SIZET),
  226. + S('x') = E(SIZET),S('X') = E(SIZET),
  227. + S('n') = E(PTR)
  228. + }, { /* 7: j-prefixed */
  229. + S('d') = E(IMAX), S('i') = E(IMAX),
  230. + S('o') = E(UMAX), S('u') = E(UMAX),
  231. + S('x') = E(UMAX), S('X') = E(UMAX),
  232. + S('n') = E(PTR)
  233. + }
  234. +};
  235. +
  236. +size_t parse_printf_format(const char *fmt, size_t n, int *types)
  237. +{
  238. + size_t i = 0;
  239. + size_t last = 0;
  240. +
  241. + memset(types, 0, n);
  242. +
  243. + while (1) {
  244. + size_t arg;
  245. + unsigned int state;
  246. +
  247. + fmt = consume_nonarg(fmt);
  248. + if (*fmt == '\0')
  249. + break;
  250. + if (*fmt == '%') {
  251. + fmt++;
  252. + continue;
  253. + }
  254. + arg = 0;
  255. + fmt = consume_argn(fmt, &arg);
  256. + /* flags */
  257. + fmt = consume_flags(fmt);
  258. + /* width */
  259. + if (*fmt == '*') {
  260. + size_t warg = 0;
  261. + fmt = consume_argn(fmt+1, &warg);
  262. + if (warg == 0)
  263. + warg = ++i;
  264. + if (warg > last)
  265. + last = warg;
  266. + if (warg <= n && types[warg-1] == NONE)
  267. + types[warg-1] = INT;
  268. + } else
  269. + fmt = consume_num(fmt);
  270. + /* precision */
  271. + if (*fmt == '.') {
  272. + fmt++;
  273. + if (*fmt == '*') {
  274. + size_t parg = 0;
  275. + fmt = consume_argn(fmt+1, &parg);
  276. + if (parg == 0)
  277. + parg = ++i;
  278. + if (parg > last)
  279. + last = parg;
  280. + if (parg <= n && types[parg-1] == NONE)
  281. + types[parg-1] = INT;
  282. + } else {
  283. + if (*fmt == '-')
  284. + fmt++;
  285. + fmt = consume_num(fmt);
  286. + }
  287. + }
  288. + /* length modifier and conversion specifier */
  289. + state = BARE;
  290. + do {
  291. + unsigned char c = *fmt++;
  292. +
  293. + if (c < 'A' || c > 'z')
  294. + continue;
  295. + state = states[state]S(c);
  296. + if (state == 0)
  297. + continue;
  298. + } while (state < STOP);
  299. +
  300. + if (state == E(NONE))
  301. + continue;
  302. +
  303. + if (arg == 0)
  304. + arg = ++i;
  305. + if (arg > last)
  306. + last = arg;
  307. + if (arg <= n)
  308. + types[arg-1] = state - STOP;
  309. + }
  310. +
  311. + if (last > n)
  312. + last = n;
  313. + for (i = 0; i < last; i++)
  314. + types[i] = pa_types[types[i]];
  315. +
  316. + return last;
  317. +}
  318. --- /dev/null
  319. +++ b/src/basic/parse-printf-format.h
  320. @@ -0,0 +1,57 @@
  321. +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
  322. +
  323. +/***
  324. + This file is part of systemd.
  325. +
  326. + Copyright 2014 Emil Renner Berthing <systemd@esmil.dk>
  327. +
  328. + With parts from the GNU C Library
  329. + Copyright 1991-2014 Free Software Foundation, Inc.
  330. +
  331. + systemd is free software; you can redistribute it and/or modify it
  332. + under the terms of the GNU Lesser General Public License as published by
  333. + the Free Software Foundation; either version 2.1 of the License, or
  334. + (at your option) any later version.
  335. +
  336. + systemd is distributed in the hope that it will be useful, but
  337. + WITHOUT ANY WARRANTY; without even the implied warranty of
  338. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  339. + Lesser General Public License for more details.
  340. +
  341. + You should have received a copy of the GNU Lesser General Public License
  342. + along with systemd; If not, see <http://www.gnu.org/licenses/>.
  343. +***/
  344. +
  345. +#pragma once
  346. +
  347. +#include "config.h"
  348. +
  349. +#if HAVE_PRINTF_H
  350. +#include <printf.h>
  351. +#else
  352. +
  353. +#include <stddef.h>
  354. +
  355. +enum { /* C type: */
  356. + PA_INT, /* int */
  357. + PA_CHAR, /* int, cast to char */
  358. + PA_WCHAR, /* wide char */
  359. + PA_STRING, /* const char *, a '\0'-terminated string */
  360. + PA_WSTRING, /* const wchar_t *, wide character string */
  361. + PA_POINTER, /* void * */
  362. + PA_FLOAT, /* float */
  363. + PA_DOUBLE, /* double */
  364. + PA_LAST
  365. +};
  366. +
  367. +/* Flag bits that can be set in a type returned by `parse_printf_format'. */
  368. +#define PA_FLAG_MASK 0xff00
  369. +#define PA_FLAG_LONG_LONG (1 << 8)
  370. +#define PA_FLAG_LONG_DOUBLE PA_FLAG_LONG_LONG
  371. +#define PA_FLAG_LONG (1 << 9)
  372. +#define PA_FLAG_SHORT (1 << 10)
  373. +#define PA_FLAG_PTR (1 << 11)
  374. +
  375. +size_t parse_printf_format(const char *fmt, size_t n, int *types);
  376. +
  377. +#endif /* HAVE_PRINTF_H */
  378. --- a/src/basic/stdio-util.h
  379. +++ b/src/basic/stdio-util.h
  380. @@ -1,12 +1,12 @@
  381. /* SPDX-License-Identifier: LGPL-2.1-or-later */
  382. #pragma once
  383. -#include <printf.h>
  384. #include <stdarg.h>
  385. #include <stdio.h>
  386. #include <sys/types.h>
  387. #include "macro.h"
  388. +#include "parse-printf-format.h"
  389. #define snprintf_ok(buf, len, fmt, ...) \
  390. ({ \
  391. --- a/src/libsystemd/sd-journal/journal-send.c
  392. +++ b/src/libsystemd/sd-journal/journal-send.c
  393. @@ -2,7 +2,6 @@
  394. #include <errno.h>
  395. #include <fcntl.h>
  396. -#include <printf.h>
  397. #include <stddef.h>
  398. #include <sys/un.h>
  399. #include <unistd.h>
  400. @@ -25,6 +24,7 @@
  401. #include "stdio-util.h"
  402. #include "string-util.h"
  403. #include "tmpfile-util.h"
  404. +#include "parse-printf-format.h"
  405. #define SNDBUF_SIZE (8*1024*1024)