119 lines
3.7 KiB
Diff
119 lines
3.7 KiB
Diff
From d2f78ba3782534f2a2719fdbda20275f6c40c073 Mon Sep 17 00:00:00 2001
|
|
From: Vratislav Podzimek <vpodzime@redhat.com>
|
|
Date: Thu, 5 May 2016 15:20:43 +0200
|
|
Subject: [PATCH] Beware of unsigned long int on 32bit arches (#1333149)
|
|
|
|
GMP has no function to assign an mpz_t instance from usigned long long int and
|
|
unsigned long int may be just a 32bit number on some architectures. So let's
|
|
just convert the number we get into a string and use the initializer from string
|
|
instead.
|
|
|
|
Signed-off-by: Vratislav Podzimek <vpodzime@redhat.com>
|
|
---
|
|
src/bs_size.c | 38 +++++++++++++++++++++++++++++++++++---
|
|
src/bs_size.h | 1 +
|
|
tests/libbytesize_unittest.py | 6 ++++++
|
|
3 files changed, 42 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/bs_size.c b/src/bs_size.c
|
|
index 71d7b48..8c55678 100644
|
|
--- a/src/bs_size.c
|
|
+++ b/src/bs_size.c
|
|
@@ -3,6 +3,7 @@
|
|
#include <langinfo.h>
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
+#include <inttypes.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <pcre.h>
|
|
@@ -329,8 +330,16 @@ BSSize bs_size_new (void) {
|
|
* Returns: a new #BSSize
|
|
*/
|
|
BSSize bs_size_new_from_bytes (uint64_t bytes, int sgn) {
|
|
+ char *num_str = NULL;
|
|
BSSize ret = bs_size_new ();
|
|
- mpz_set_ui (ret->bytes, bytes);
|
|
+ int ok = 0;
|
|
+
|
|
+ ok = asprintf (&num_str, "%"PRIu64, bytes);
|
|
+ if (ok == -1)
|
|
+ /* probably cannot allocate memory, there's nothing more we can do */
|
|
+ return ret;
|
|
+ mpz_set_str (ret->bytes, num_str, 10);
|
|
+ free (num_str);
|
|
if (sgn == -1)
|
|
mpz_neg (ret->bytes, ret->bytes);
|
|
return ret;
|
|
@@ -475,13 +484,36 @@ BSSize bs_size_new_from_size (const BSSize size) {
|
|
* Returns: the @size in a number of bytes
|
|
*/
|
|
uint64_t bs_size_get_bytes (const BSSize size, int *sgn, BSError **error) {
|
|
- if (mpz_cmp_ui (size->bytes, UINT64_MAX) > 0) {
|
|
+ char *num_str = NULL;
|
|
+ mpz_t max;
|
|
+ uint64_t ret = 0;
|
|
+ int ok = 0;
|
|
+
|
|
+ mpz_init2 (max, (mp_bitcnt_t) 64);
|
|
+ ok = asprintf (&num_str, "%"PRIu64, UINT64_MAX);
|
|
+ if (ok == -1) {
|
|
+ /* we probably cannot allocate memory so we are doomed */
|
|
+ set_error (error, BS_ERROR_FAIL, strdup("Failed to allocate memory"));
|
|
+ mpz_clear (max);
|
|
+ return 0;
|
|
+ }
|
|
+ mpz_set_str (max, num_str, 10);
|
|
+ free (num_str);
|
|
+ if (mpz_cmp (size->bytes, max) > 0) {
|
|
set_error (error, BS_ERROR_OVER, strdup("The size is too big, cannot be returned as a 64bit number of bytes"));
|
|
return 0;
|
|
}
|
|
+ mpz_clear (max);
|
|
if (sgn)
|
|
*sgn = mpz_sgn (size->bytes);
|
|
- return (uint64_t) mpz_get_ui (size->bytes);
|
|
+ if (mpz_cmp_ui (size->bytes, UINT64_MAX) <= 0)
|
|
+ return (uint64_t) mpz_get_ui (size->bytes);
|
|
+ else {
|
|
+ num_str = bs_size_get_bytes_str (size);
|
|
+ ret = strtoull (num_str, NULL, 10);
|
|
+ free (num_str);
|
|
+ return ret;
|
|
+ }
|
|
}
|
|
|
|
/**
|
|
diff --git a/src/bs_size.h b/src/bs_size.h
|
|
index 0a961df..e7e29c6 100644
|
|
--- a/src/bs_size.h
|
|
+++ b/src/bs_size.h
|
|
@@ -24,6 +24,7 @@ typedef enum {
|
|
BS_ERROR_INVALID_SPEC,
|
|
BS_ERROR_OVER,
|
|
BS_ERROR_ZERO_DIV,
|
|
+ BS_ERROR_FAIL
|
|
} BSErrorCode;
|
|
|
|
/**
|
|
diff --git a/tests/libbytesize_unittest.py b/tests/libbytesize_unittest.py
|
|
index ce4b01d..e57dc0b 100755
|
|
--- a/tests/libbytesize_unittest.py
|
|
+++ b/tests/libbytesize_unittest.py
|
|
@@ -123,6 +123,12 @@ class SizeTestCase(unittest.TestCase):
|
|
actual = SizeStruct.new_from_bytes(1024, -1).get_bytes()
|
|
expected = (1024, -1)
|
|
self.assertEqual(actual, expected)
|
|
+
|
|
+ # now let's try something bigger than MAXUINT32
|
|
+ actual = SizeStruct.new_from_bytes(5718360*1024, 1).get_bytes()
|
|
+ expected = (5718360*1024, 1)
|
|
+ self.assertEqual(actual, expected)
|
|
+
|
|
#enddef
|
|
|
|
def testNewFromSizeStruct(self):
|
|
--
|
|
2.5.5
|
|
|