Skip to content

Commit

Permalink
Merge efe7f7a into 9b8ca93
Browse files Browse the repository at this point in the history
  • Loading branch information
jamadden committed Aug 28, 2018
2 parents 9b8ca93 + efe7f7a commit 2afcf87
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Expand Up @@ -10,6 +10,8 @@ matrix:
python: 3.5
- os: linux
python: 3.6
# Test for https://github.com/zopefoundation/persistent/issues/86
env: CFLAGS="-fno-wrapv"
- os: linux
python: pypy
- os: linux
Expand Down
5 changes: 4 additions & 1 deletion CHANGES.rst
Expand Up @@ -4,7 +4,10 @@
4.4.2 (unreleased)
------------------

- Nothing changed yet.
- Explicitly use unsigned constants for packing and unpacking C
timestamps, fixing an arithmetic issue for GCC when optimizations
are enabled and ``-fwrapv`` is *not* enabled. See `issue 86
<https://github.com/zopefoundation/persistent/issues/86>`_.


4.4.1 (2018-08-23)
Expand Down
21 changes: 15 additions & 6 deletions persistent/_timestamp.c
Expand Up @@ -35,7 +35,7 @@ static char TimeStampModule_doc[] =
To get (close to) the original seconds back, use
`TS_UNPACK_UINT32_FROM_BYTES` and *multiply* by this number.
*/
#define TS_SECOND_BYTES_BIAS ((double)60) / ((double)(0x10000)) / ((double)(0x10000))
#define TS_SECOND_BYTES_BIAS ((double)((double)60) / ((double)(0x10000)) / ((double)(0x10000)))
#define TS_BASE_YEAR 1900
#define TS_MINUTES_PER_DAY 1440
/* We pretend there are always 31 days in a month; this has us using
Expand All @@ -45,6 +45,15 @@ static char TimeStampModule_doc[] =
#define TS_MINUTES_PER_MONTH (TS_DAYS_PER_MONTH * TS_MINUTES_PER_DAY)
#define TS_MINUTES_PER_YEAR (TS_MINUTES_PER_MONTH * TS_MONTHS_PER_YEAR)

/* The U suffixes matter on these constants to be sure
the compiler generates the appropriate instructions when
optimizations are enabled. On x86_64 GCC, if -fno-wrapv is given
and -O is used, the compiler might choose to treat these as 32 bit
signed quantities otherwise, producing incorrect results on
some corner cases. See
https://github.com/zopefoundation/persistent/issues/86
*/

/**
* Given an unsigned int *v*, pack it into the four
* unsigned char bytes beginning at *bytes*. If *v* is larger
Expand All @@ -56,10 +65,10 @@ static char TimeStampModule_doc[] =
*
*/
#define TS_PACK_UINT32_INTO_BYTES(v, bytes) do { \
*(bytes) = v / 0x1000000; \
*(bytes + 1) = (v % 0x1000000) / 0x10000; \
*(bytes + 2) = (v % 0x10000) / 0x100; \
*(bytes + 3) = v % 0x100; \
*(bytes) = v / 0x1000000U; \
*(bytes + 1) = (v % 0x1000000U) / 0x10000U; \
*(bytes + 2) = (v % 0x10000U) / 0x100U; \
*(bytes + 3) = v % 0x100U; \
} while (0)

/**
Expand All @@ -71,7 +80,7 @@ static char TimeStampModule_doc[] =
* may not exactly match the original value. If the original value
* was greater than 2^31 it will definitely not match.
*/
#define TS_UNPACK_UINT32_FROM_BYTES(bytes) (*(bytes) * 0x1000000 + *(bytes + 1) * 0x10000 + *(bytes + 2) * 0x100 + *(bytes + 3))
#define TS_UNPACK_UINT32_FROM_BYTES(bytes) (*(bytes) * 0x1000000U + *(bytes + 1) * 0x10000U + *(bytes + 2) * 0x100U + *(bytes + 3))

typedef struct
{
Expand Down

0 comments on commit 2afcf87

Please sign in to comment.