aboutsummaryrefslogtreecommitdiff
path: root/libbb/safe_strtol.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbb/safe_strtol.c')
-rw-r--r--libbb/safe_strtol.c102
1 files changed, 77 insertions, 25 deletions
diff --git a/libbb/safe_strtol.c b/libbb/safe_strtol.c
index 027fc1e62..a7f012fbc 100644
--- a/libbb/safe_strtol.c
+++ b/libbb/safe_strtol.c
@@ -7,21 +7,10 @@
* Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
*/
-#include <stdlib.h>
-#include <errno.h>
#include <assert.h>
#include "libbb.h"
-int safe_strtoi(char *arg, int* value)
-{
- int error;
- long lvalue = *value;
- error = safe_strtol(arg, &lvalue);
- *value = (int) lvalue;
- return error;
-}
-
-int safe_strtod(char *arg, double* value)
+int safe_strtod(const char *arg, double* value)
{
char *endptr;
int errno_save = errno;
@@ -29,69 +18,132 @@ int safe_strtod(char *arg, double* value)
assert(arg!=NULL);
errno = 0;
*value = strtod(arg, &endptr);
- if (errno != 0 || *endptr!='\0' || endptr==arg) {
+ if (errno != 0 || *endptr != '\0' || endptr == arg) {
return 1;
}
errno = errno_save;
return 0;
}
-int safe_strtol(char *arg, long* value)
+int safe_strtoull(const char *arg, unsigned long long* value)
{
char *endptr;
int errno_save = errno;
assert(arg!=NULL);
+ if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */
+ return 1;
errno = 0;
- *value = strtol(arg, &endptr, 0);
- if (errno != 0 || *endptr!='\0' || endptr==arg) {
+ *value = strtoull(arg, &endptr, 0);
+ if (errno != 0 || *endptr != '\0' || endptr == arg) {
return 1;
}
errno = errno_save;
return 0;
}
-int safe_strtoul(char *arg, unsigned long* value)
+int safe_strtoll(const char *arg, long long* value)
{
char *endptr;
int errno_save = errno;
assert(arg!=NULL);
errno = 0;
- *value = strtoul(arg, &endptr, 0);
- if (errno != 0 || *endptr!='\0' || endptr==arg) {
+ *value = strtoll(arg, &endptr, 0);
+ if (errno != 0 || *endptr != '\0' || endptr == arg) {
return 1;
}
errno = errno_save;
return 0;
}
-int safe_strtoll(char *arg, long long* value)
+int safe_strtoul(const char *arg, unsigned long* value)
{
char *endptr;
int errno_save = errno;
assert(arg!=NULL);
+ if (!isdigit(arg[0])) /* strtouXX takes minus signs w/o error! :( */
+ return 1;
errno = 0;
- *value = strtoll(arg, &endptr, 0);
- if (errno != 0 || *endptr!='\0' || endptr==arg) {
+ *value = strtoul(arg, &endptr, 0);
+ if (errno != 0 || *endptr != '\0' || endptr == arg) {
return 1;
}
errno = errno_save;
return 0;
}
-int safe_strtoull(char *arg, unsigned long long* value)
+int safe_strtol(const char *arg, long* value)
{
char *endptr;
int errno_save = errno;
assert(arg!=NULL);
errno = 0;
- *value = strtoull(arg, &endptr, 0);
- if (errno != 0 || *endptr!='\0' || endptr==arg) {
+ *value = strtol(arg, &endptr, 0);
+ if (errno != 0 || *endptr != '\0' || endptr == arg) {
return 1;
}
errno = errno_save;
return 0;
}
+
+/* TODO: This is what uclibc is doing. Try to do the same? */
+
+#if 0
+#if defined __HAVE_ELF__
+
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+
+#else /* !defined __HAVE_ELF__ */
+
+# define strong_alias(name, aliasname) _strong_alias (name, aliasname)
+# define _strong_alias(name, aliasname) \
+ __asm__(".global " __C_SYMBOL_PREFIX__ #aliasname "\n" \
+ ".set " __C_SYMBOL_PREFIX__ #aliasname "," __C_SYMBOL_PREFIX__ #name);
+
+#endif
+#endif
+
+int safe_strtoi(const char *arg, int* value)
+{
+ if (sizeof(long) == sizeof(int)) {
+ return safe_strtol(arg, (long*)value);
+ } else {
+ int error;
+ long lvalue = *value;
+ error = safe_strtol(arg, &lvalue);
+ if (lvalue < INT_MIN || lvalue > INT_MAX)
+ return 1;
+ *value = (int) lvalue;
+ return error;
+ }
+}
+
+int safe_strtou(const char *arg, unsigned* value)
+{
+ if (sizeof(unsigned long) == sizeof(unsigned)) {
+ return safe_strtoul(arg, (unsigned long*)value);
+ } else {
+ int error;
+ unsigned long lvalue = *value;
+ error = safe_strtoul(arg, &lvalue);
+ if (lvalue > UINT_MAX)
+ return 1;
+ *value = (unsigned) lvalue;
+ return error;
+ }
+}
+
+int BUG_safe_strtou32_unimplemented(void);
+int safe_strtou32(const char *arg, uint32_t* value)
+{
+ if (sizeof(uint32_t) == sizeof(unsigned))
+ return safe_strtou(arg, (unsigned*)value);
+ if (sizeof(uint32_t) == sizeof(unsigned long))
+ return safe_strtoul(arg, (unsigned long*)value);
+ return BUG_safe_strtou32_unimplemented();
+}