Skip to content

Commit

Permalink
Beware of unsigned long int on 32bit arches (#1333149)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vpodzime committed May 5, 2016
1 parent d01997e commit 894064a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
27 changes: 24 additions & 3 deletions src/bs_size.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -329,8 +330,12 @@ 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);

asprintf (&num_str, "%"PRIu64, bytes);
mpz_set_str (ret->bytes, num_str, 10);
free (num_str);
if (sgn == -1)
mpz_neg (ret->bytes, ret->bytes);
return ret;
Expand Down Expand Up @@ -475,13 +480,29 @@ 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;

mpz_init2 (max, (mp_bitcnt_t) 64);
asprintf (&num_str, "%"PRIu64, UINT64_MAX);
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;
}
}

/**
Expand Down
6 changes: 6 additions & 0 deletions tests/libbytesize_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ def testNewFromBytes(self):
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):
Expand Down

0 comments on commit 894064a

Please sign in to comment.