summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlejandro Colomar <alx@kernel.org>2024-04-18 14:13:28 +0200
committerAlejandro Colomar <alx@kernel.org>2024-04-18 14:13:54 +0200
commit25fdce75ba7ef240b01c69af5b8dd26d0e648185 (patch)
treec40002649f27ef207f4a0ad888149ad9da712136
parentfb780435921038f6264fcbc74fe424e7d65b7de3 (diff)
include/a2i/strtoi.h, lib/src/a2i/strtoi.c: Don't inline these functions
We've learnt from the xz backdoor that dependencies can be very dangerous. By not inlining, we isolate the damage that our library could cause. If a bug is ever found here, fixing the library should be enough. If one wants to optimize, they still can use LTO. Signed-off-by: Alejandro Colomar <alx@kernel.org>
-rw-r--r--include/a2i/strtoi.h101
-rw-r--r--lib/src/a2i/strtoi.c92
2 files changed, 92 insertions, 101 deletions
diff --git a/include/a2i/strtoi.h b/include/a2i/strtoi.h
index aa5d5b4..d202da3 100644
--- a/include/a2i/strtoi.h
+++ b/include/a2i/strtoi.h
@@ -6,62 +6,12 @@
#define INCLUDE_A2I_STRTOI_H_
-#include <errno.h>
-#include <inttypes.h>
-#include <stddef.h>
#include <stdint.h>
-#include <sys/param.h>
#include <a2i/attr.h>
-#include <a2i/inline.h>
#include <a2i/qual.h>
-#define a2i_strtoI(TYPE, s, endp, base, min, max, status) \
-({ \
- const char *s_ = s; \
- char **endp_ = endp; \
- int base_ = base; \
- TYPE min_ = min; \
- TYPE max_ = max; \
- int *status_ = status; \
- \
- int errno_saved_, st_; \
- char *e_; \
- TYPE n_; \
- \
- if (endp_ == NULL) \
- endp_ = &e_; \
- if (status_ == NULL) \
- status_ = &st_; \
- \
- if (base != 0 && (base_ < 2 || base_ > 36)) { \
- *status_ = EINVAL; \
- n_ = 0; \
- \
- } else { \
- errno_saved_ = errno; \
- errno = 0; \
- n_ = _Generic((TYPE) 0, \
- intmax_t: strtoimax, \
- uintmax_t: strtoumax \
- )(s_, endp_, base_); \
- \
- if (*endp_ == s_) \
- *status_ = ECANCELED; \
- else if (errno == ERANGE || n_ < min_ || n_ > max_) \
- *status_ = ERANGE; \
- else if (**endp_ != '\0') \
- *status_ = ENOTSUP; \
- else \
- *status_ = 0; \
- \
- errno = errno_saved_; \
- } \
- MAX(min_, MIN(max_, n_)); \
-})
-
-
#if defined(__clang__)
# pragma clang assume_nonnull begin
#endif
@@ -69,57 +19,22 @@ A2I_ATTR_ACCESS(read_only, 1)
A2I_ATTR_ACCESS(write_only, 2)
A2I_ATTR_ACCESS(write_only, 6)
A2I_ATTR_STRING(1)
-a2i_inline intmax_t a2i_strtoi(const char *s,
- char **a2i_nullable restrict endp, int base,
- intmax_t min, intmax_t max, int *a2i_nullable restrict status);
+intmax_t a2i_strtoi(const char *s, char **a2i_nullable restrict endp,
+ int base, intmax_t min, intmax_t max, int *a2i_nullable restrict status);
+
A2I_ATTR_ACCESS(read_only, 1)
A2I_ATTR_ACCESS(write_only, 2)
A2I_ATTR_ACCESS(write_only, 6)
A2I_ATTR_STRING(1)
-a2i_inline uintmax_t a2i_strtou(const char *s,
- char **a2i_nullable restrict endp, int base,
- uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
+uintmax_t a2i_strtou(const char *s, char **a2i_nullable restrict endp,
+ int base, uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
+
A2I_ATTR_ACCESS(read_only, 1)
A2I_ATTR_ACCESS(write_only, 2)
A2I_ATTR_ACCESS(write_only, 6)
A2I_ATTR_STRING(1)
-a2i_inline uintmax_t a2i_strtou_noneg(const char *s,
- char **a2i_nullable restrict endp, int base,
- uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
-
-
-a2i_inline intmax_t
-a2i_strtoi(const char *s,
- char **a2i_nullable restrict endp, int base,
- intmax_t min, intmax_t max, int *a2i_nullable restrict status)
-{
- return a2i_strtoI(intmax_t, s, endp, base, min, max, status);
-}
-
-
-a2i_inline uintmax_t
-a2i_strtou(const char *s,
- char **a2i_nullable restrict endp, int base,
- uintmax_t min, uintmax_t max, int *a2i_nullable restrict status)
-{
- return a2i_strtoI(uintmax_t, s, endp, base, min, max, status);
-}
-
-
-a2i_inline uintmax_t
-a2i_strtou_noneg(const char *s,
- char **a2i_nullable restrict endp, int base,
- uintmax_t min, uintmax_t max, int *a2i_nullable restrict status)
-{
- int st;
-
- if (status == NULL)
- status = &st;
- if (a2i_strtoi(s, endp, base, 0, 1, status) == 0 && *status == ERANGE)
- return min;
-
- return a2i_strtou(s, endp, base, min, max, status);
-}
+uintmax_t a2i_strtou_noneg(const char *s, char **a2i_nullable restrict endp,
+ int base, uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
#if defined(__clang__)
# pragma clang assume_nonnull end
#endif
diff --git a/lib/src/a2i/strtoi.c b/lib/src/a2i/strtoi.c
index d36ac93..75563f1 100644
--- a/lib/src/a2i/strtoi.c
+++ b/lib/src/a2i/strtoi.c
@@ -4,19 +4,95 @@
#include <a2i/strtoi.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
#include <stdint.h>
+#include <sys/param.h>
#include <a2i/qual.h>
-#pragma clang assume_nonnull begin
-extern inline intmax_t a2i_strtoi(const char *s,
+#define a2i_strtoI(TYPE, s, endp, base, min, max, status) \
+({ \
+ const char *s_ = s; \
+ char **endp_ = endp; \
+ int base_ = base; \
+ TYPE min_ = min; \
+ TYPE max_ = max; \
+ int *status_ = status; \
+ \
+ int errno_saved_, st_; \
+ char *e_; \
+ TYPE n_; \
+ \
+ if (endp_ == NULL) \
+ endp_ = &e_; \
+ if (status_ == NULL) \
+ status_ = &st_; \
+ \
+ if (base != 0 && (base_ < 2 || base_ > 36)) { \
+ *status_ = EINVAL; \
+ n_ = 0; \
+ \
+ } else { \
+ errno_saved_ = errno; \
+ errno = 0; \
+ n_ = _Generic((TYPE) 0, \
+ intmax_t: strtoimax, \
+ uintmax_t: strtoumax \
+ )(s_, endp_, base_); \
+ \
+ if (*endp_ == s_) \
+ *status_ = ECANCELED; \
+ else if (errno == ERANGE || n_ < min_ || n_ > max_) \
+ *status_ = ERANGE; \
+ else if (**endp_ != '\0') \
+ *status_ = ENOTSUP; \
+ else \
+ *status_ = 0; \
+ \
+ errno = errno_saved_; \
+ } \
+ MAX(min_, MIN(max_, n_)); \
+})
+
+
+#if defined(__clang__)
+# pragma clang assume_nonnull begin
+#endif
+intmax_t
+a2i_strtoi(const char *s,
char **a2i_nullable restrict endp, int base,
- intmax_t min, intmax_t max, int *a2i_nullable restrict status);
-extern inline uintmax_t a2i_strtou(const char *s,
+ intmax_t min, intmax_t max, int *a2i_nullable restrict status)
+{
+ return a2i_strtoI(intmax_t, s, endp, base, min, max, status);
+}
+
+
+uintmax_t
+a2i_strtou(const char *s,
char **a2i_nullable restrict endp, int base,
- uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
-extern inline uintmax_t a2i_strtou_noneg(const char *s,
+ uintmax_t min, uintmax_t max, int *a2i_nullable restrict status)
+{
+ return a2i_strtoI(uintmax_t, s, endp, base, min, max, status);
+}
+
+
+uintmax_t
+a2i_strtou_noneg(const char *s,
char **a2i_nullable restrict endp, int base,
- uintmax_t min, uintmax_t max, int *a2i_nullable restrict status);
-#pragma clang assume_nonnull end
+ uintmax_t min, uintmax_t max, int *a2i_nullable restrict status)
+{
+ int st;
+
+ if (status == NULL)
+ status = &st;
+ if (a2i_strtoi(s, endp, base, 0, 1, status) == 0 && *status == ERANGE)
+ return min;
+
+ return a2i_strtou(s, endp, base, min, max, status);
+}
+#if defined(__clang__)
+# pragma clang assume_nonnull end
+#endif