cutils: add qemu_strtoi & qemu_strtoui parsers for int/unsigned int types
There are qemu_strtoNN functions for various sized integers. This adds two more for plain int & unsigned int types, with suitable range checking. Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
		
				
					committed by
					
						 Daniel P. Berrangé
						Daniel P. Berrangé
					
				
			
			
				
	
			
			
			
						parent
						
							63bab2b696
						
					
				
				
					commit
					473a2a331e
				
			| @@ -126,6 +126,10 @@ time_t mktimegm(struct tm *tm); | ||||
| int qemu_fdatasync(int fd); | ||||
| int fcntl_setfl(int fd, int flag); | ||||
| int qemu_parse_fd(const char *param); | ||||
| int qemu_strtoi(const char *nptr, const char **endptr, int base, | ||||
|                 int *result); | ||||
| int qemu_strtoui(const char *nptr, const char **endptr, int base, | ||||
|                  unsigned int *result); | ||||
| int qemu_strtol(const char *nptr, const char **endptr, int base, | ||||
|                 long *result); | ||||
| int qemu_strtoul(const char *nptr, const char **endptr, int base, | ||||
|   | ||||
| @@ -223,6 +223,583 @@ static void test_parse_uint_full_correct(void) | ||||
|     g_assert_cmpint(i, ==, 123); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_correct(void) | ||||
| { | ||||
|     const char *str = "12345 foo"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 12345); | ||||
|     g_assert(endptr == str + 5); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_null(void) | ||||
| { | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(NULL, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == NULL); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_empty(void) | ||||
| { | ||||
|     const char *str = ""; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_whitespace(void) | ||||
| { | ||||
|     const char *str = "  \t  "; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_invalid(void) | ||||
| { | ||||
|     const char *str = "   xxxx  \t abc"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_trailing(void) | ||||
| { | ||||
|     const char *str = "123xxx"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 123); | ||||
|     g_assert(endptr == str + 3); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_octal(void) | ||||
| { | ||||
|     const char *str = "0123"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 8, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 0123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|  | ||||
|     res = 999; | ||||
|     endptr = &f; | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 0123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_decimal(void) | ||||
| { | ||||
|     const char *str = "0123"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 10, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|  | ||||
|     str = "123"; | ||||
|     res = 999; | ||||
|     endptr = &f; | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_hex(void) | ||||
| { | ||||
|     const char *str = "0123"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 16, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 0x123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|  | ||||
|     str = "0x123"; | ||||
|     res = 999; | ||||
|     endptr = &f; | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 0x123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_max(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%d", INT_MAX); | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, INT_MAX); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_overflow(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%lld", (long long)INT_MAX + 1ll); | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -ERANGE); | ||||
|     g_assert_cmpint(res, ==, INT_MAX); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_underflow(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%lld", (long long)INT_MIN - 1ll); | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err  = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -ERANGE); | ||||
|     g_assert_cmpint(res, ==, INT_MIN); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_negative(void) | ||||
| { | ||||
|     const char *str = "  \t -321"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, -321); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_full_correct(void) | ||||
| { | ||||
|     const char *str = "123"; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, 123); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_full_null(void) | ||||
| { | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(NULL, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == NULL); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_full_empty(void) | ||||
| { | ||||
|     const char *str = ""; | ||||
|     int res = 999L; | ||||
|     int err; | ||||
|  | ||||
|     err =  qemu_strtoi(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_full_negative(void) | ||||
| { | ||||
|     const char *str = " \t -321"; | ||||
|     int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, -321); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_full_trailing(void) | ||||
| { | ||||
|     const char *str = "123xxx"; | ||||
|     int res; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoi_full_max(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%d", INT_MAX); | ||||
|     int res; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoi(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpint(res, ==, INT_MAX); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_correct(void) | ||||
| { | ||||
|     const char *str = "12345 foo"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, 12345); | ||||
|     g_assert(endptr == str + 5); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_null(void) | ||||
| { | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(NULL, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == NULL); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_empty(void) | ||||
| { | ||||
|     const char *str = ""; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_whitespace(void) | ||||
| { | ||||
|     const char *str = "  \t  "; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_invalid(void) | ||||
| { | ||||
|     const char *str = "   xxxx  \t abc"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
|     g_assert(endptr == str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_trailing(void) | ||||
| { | ||||
|     const char *str = "123xxx"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, 123); | ||||
|     g_assert(endptr == str + 3); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_octal(void) | ||||
| { | ||||
|     const char *str = "0123"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 8, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, 0123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|  | ||||
|     res = 999; | ||||
|     endptr = &f; | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, 0123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_decimal(void) | ||||
| { | ||||
|     const char *str = "0123"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 10, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, 123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|  | ||||
|     str = "123"; | ||||
|     res = 999; | ||||
|     endptr = &f; | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, 123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_hex(void) | ||||
| { | ||||
|     const char *str = "0123"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 16, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmphex(res, ==, 0x123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|  | ||||
|     str = "0x123"; | ||||
|     res = 999; | ||||
|     endptr = &f; | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmphex(res, ==, 0x123); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_max(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%u", UINT_MAX); | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmphex(res, ==, UINT_MAX); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_overflow(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%lld", (long long)UINT_MAX + 1ll); | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -ERANGE); | ||||
|     g_assert_cmphex(res, ==, UINT_MAX); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_underflow(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%lld", (long long)INT_MIN - 1ll); | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err  = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -ERANGE); | ||||
|     g_assert_cmpuint(res, ==, (unsigned int)-1); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_negative(void) | ||||
| { | ||||
|     const char *str = "  \t -321"; | ||||
|     char f = 'X'; | ||||
|     const char *endptr = &f; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, &endptr, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, (unsigned int)-321); | ||||
|     g_assert(endptr == str + strlen(str)); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_full_correct(void) | ||||
| { | ||||
|     const char *str = "123"; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, 123); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_full_null(void) | ||||
| { | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(NULL, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_full_empty(void) | ||||
| { | ||||
|     const char *str = ""; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
| } | ||||
| static void test_qemu_strtoui_full_negative(void) | ||||
| { | ||||
|     const char *str = " \t -321"; | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, NULL, 0, &res); | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmpuint(res, ==, (unsigned int)-321); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_full_trailing(void) | ||||
| { | ||||
|     const char *str = "123xxx"; | ||||
|     unsigned int res; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, -EINVAL); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtoui_full_max(void) | ||||
| { | ||||
|     char *str = g_strdup_printf("%u", UINT_MAX); | ||||
|     unsigned int res = 999; | ||||
|     int err; | ||||
|  | ||||
|     err = qemu_strtoui(str, NULL, 0, &res); | ||||
|  | ||||
|     g_assert_cmpint(err, ==, 0); | ||||
|     g_assert_cmphex(res, ==, UINT_MAX); | ||||
|     g_free(str); | ||||
| } | ||||
|  | ||||
| static void test_qemu_strtol_correct(void) | ||||
| { | ||||
|     const char *str = "12345 foo"; | ||||
| @@ -1612,6 +2189,86 @@ int main(int argc, char **argv) | ||||
|     g_test_add_func("/cutils/parse_uint_full/correct", | ||||
|                     test_parse_uint_full_correct); | ||||
|  | ||||
|     /* qemu_strtoi() tests */ | ||||
|     g_test_add_func("/cutils/qemu_strtoi/correct", | ||||
|                     test_qemu_strtoi_correct); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/null", | ||||
|                     test_qemu_strtoi_null); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/empty", | ||||
|                     test_qemu_strtoi_empty); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/whitespace", | ||||
|                     test_qemu_strtoi_whitespace); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/invalid", | ||||
|                     test_qemu_strtoi_invalid); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/trailing", | ||||
|                     test_qemu_strtoi_trailing); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/octal", | ||||
|                     test_qemu_strtoi_octal); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/decimal", | ||||
|                     test_qemu_strtoi_decimal); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/hex", | ||||
|                     test_qemu_strtoi_hex); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/max", | ||||
|                     test_qemu_strtoi_max); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/overflow", | ||||
|                     test_qemu_strtoi_overflow); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/underflow", | ||||
|                     test_qemu_strtoi_underflow); | ||||
|     g_test_add_func("/cutils/qemu_strtoi/negative", | ||||
|                     test_qemu_strtoi_negative); | ||||
|     g_test_add_func("/cutils/qemu_strtoi_full/correct", | ||||
|                     test_qemu_strtoi_full_correct); | ||||
|     g_test_add_func("/cutils/qemu_strtoi_full/null", | ||||
|                     test_qemu_strtoi_full_null); | ||||
|     g_test_add_func("/cutils/qemu_strtoi_full/empty", | ||||
|                     test_qemu_strtoi_full_empty); | ||||
|     g_test_add_func("/cutils/qemu_strtoi_full/negative", | ||||
|                     test_qemu_strtoi_full_negative); | ||||
|     g_test_add_func("/cutils/qemu_strtoi_full/trailing", | ||||
|                     test_qemu_strtoi_full_trailing); | ||||
|     g_test_add_func("/cutils/qemu_strtoi_full/max", | ||||
|                     test_qemu_strtoi_full_max); | ||||
|  | ||||
|     /* qemu_strtoui() tests */ | ||||
|     g_test_add_func("/cutils/qemu_strtoui/correct", | ||||
|                     test_qemu_strtoui_correct); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/null", | ||||
|                     test_qemu_strtoui_null); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/empty", | ||||
|                     test_qemu_strtoui_empty); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/whitespace", | ||||
|                     test_qemu_strtoui_whitespace); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/invalid", | ||||
|                     test_qemu_strtoui_invalid); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/trailing", | ||||
|                     test_qemu_strtoui_trailing); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/octal", | ||||
|                     test_qemu_strtoui_octal); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/decimal", | ||||
|                     test_qemu_strtoui_decimal); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/hex", | ||||
|                     test_qemu_strtoui_hex); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/max", | ||||
|                     test_qemu_strtoui_max); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/overflow", | ||||
|                     test_qemu_strtoui_overflow); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/underflow", | ||||
|                     test_qemu_strtoui_underflow); | ||||
|     g_test_add_func("/cutils/qemu_strtoui/negative", | ||||
|                     test_qemu_strtoui_negative); | ||||
|     g_test_add_func("/cutils/qemu_strtoui_full/correct", | ||||
|                     test_qemu_strtoui_full_correct); | ||||
|     g_test_add_func("/cutils/qemu_strtoui_full/null", | ||||
|                     test_qemu_strtoui_full_null); | ||||
|     g_test_add_func("/cutils/qemu_strtoui_full/empty", | ||||
|                     test_qemu_strtoui_full_empty); | ||||
|     g_test_add_func("/cutils/qemu_strtoui_full/negative", | ||||
|                     test_qemu_strtoui_full_negative); | ||||
|     g_test_add_func("/cutils/qemu_strtoui_full/trailing", | ||||
|                     test_qemu_strtoui_full_trailing); | ||||
|     g_test_add_func("/cutils/qemu_strtoui_full/max", | ||||
|                     test_qemu_strtoui_full_max); | ||||
|  | ||||
|     /* qemu_strtol() tests */ | ||||
|     g_test_add_func("/cutils/qemu_strtol/correct", | ||||
|                     test_qemu_strtol_correct); | ||||
|   | ||||
							
								
								
									
										109
									
								
								util/cutils.c
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								util/cutils.c
									
									
									
									
									
								
							| @@ -297,6 +297,115 @@ static int check_strtox_error(const char *nptr, char *ep, | ||||
|     return -libc_errno; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Convert string @nptr to an integer, and store it in @result. | ||||
|  * | ||||
|  * This is a wrapper around strtol() that is harder to misuse. | ||||
|  * Semantics of @nptr, @endptr, @base match strtol() with differences | ||||
|  * noted below. | ||||
|  * | ||||
|  * @nptr may be null, and no conversion is performed then. | ||||
|  * | ||||
|  * If no conversion is performed, store @nptr in *@endptr and return | ||||
|  * -EINVAL. | ||||
|  * | ||||
|  * If @endptr is null, and the string isn't fully converted, return | ||||
|  * -EINVAL.  This is the case when the pointer that would be stored in | ||||
|  * a non-null @endptr points to a character other than '\0'. | ||||
|  * | ||||
|  * If the conversion overflows @result, store INT_MAX in @result, | ||||
|  * and return -ERANGE. | ||||
|  * | ||||
|  * If the conversion underflows @result, store INT_MIN in @result, | ||||
|  * and return -ERANGE. | ||||
|  * | ||||
|  * Else store the converted value in @result, and return zero. | ||||
|  */ | ||||
| int qemu_strtoi(const char *nptr, const char **endptr, int base, | ||||
|                 int *result) | ||||
| { | ||||
|     char *ep; | ||||
|     long long lresult; | ||||
|  | ||||
|     if (!nptr) { | ||||
|         if (endptr) { | ||||
|             *endptr = nptr; | ||||
|         } | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     errno = 0; | ||||
|     lresult = strtoll(nptr, &ep, base); | ||||
|     if (lresult < INT_MIN) { | ||||
|         *result = INT_MIN; | ||||
|         errno = ERANGE; | ||||
|     } else if (lresult > INT_MAX) { | ||||
|         *result = INT_MAX; | ||||
|         errno = ERANGE; | ||||
|     } else { | ||||
|         *result = lresult; | ||||
|     } | ||||
|     return check_strtox_error(nptr, ep, endptr, errno); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Convert string @nptr to an unsigned integer, and store it in @result. | ||||
|  * | ||||
|  * This is a wrapper around strtoul() that is harder to misuse. | ||||
|  * Semantics of @nptr, @endptr, @base match strtoul() with differences | ||||
|  * noted below. | ||||
|  * | ||||
|  * @nptr may be null, and no conversion is performed then. | ||||
|  * | ||||
|  * If no conversion is performed, store @nptr in *@endptr and return | ||||
|  * -EINVAL. | ||||
|  * | ||||
|  * If @endptr is null, and the string isn't fully converted, return | ||||
|  * -EINVAL.  This is the case when the pointer that would be stored in | ||||
|  * a non-null @endptr points to a character other than '\0'. | ||||
|  * | ||||
|  * If the conversion overflows @result, store UINT_MAX in @result, | ||||
|  * and return -ERANGE. | ||||
|  * | ||||
|  * Else store the converted value in @result, and return zero. | ||||
|  * | ||||
|  * Note that a number with a leading minus sign gets converted without | ||||
|  * the minus sign, checked for overflow (see above), then negated (in | ||||
|  * @result's type).  This is exactly how strtoul() works. | ||||
|  */ | ||||
| int qemu_strtoui(const char *nptr, const char **endptr, int base, | ||||
|                  unsigned int *result) | ||||
| { | ||||
|     char *ep; | ||||
|     long long lresult; | ||||
|  | ||||
|     if (!nptr) { | ||||
|         if (endptr) { | ||||
|             *endptr = nptr; | ||||
|         } | ||||
|         return -EINVAL; | ||||
|     } | ||||
|  | ||||
|     errno = 0; | ||||
|     lresult = strtoull(nptr, &ep, base); | ||||
|  | ||||
|     /* Windows returns 1 for negative out-of-range values.  */ | ||||
|     if (errno == ERANGE) { | ||||
|         *result = -1; | ||||
|     } else { | ||||
|         if (lresult > UINT_MAX) { | ||||
|             *result = UINT_MAX; | ||||
|             errno = ERANGE; | ||||
|         } else if (lresult < INT_MIN) { | ||||
|             *result = UINT_MAX; | ||||
|             errno = ERANGE; | ||||
|         } else { | ||||
|             *result = lresult; | ||||
|         } | ||||
|     } | ||||
|     return check_strtox_error(nptr, ep, endptr, errno); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Convert string @nptr to a long integer, and store it in @result. | ||||
|  * | ||||
|   | ||||
		Reference in New Issue
	
	Block a user