diff options
author | David Cole <david.cole@kitware.com> | 2012-12-05 15:30:06 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2012-12-05 15:30:06 (GMT) |
commit | a4e0bba98770094050cad5cf337eae4246ce0f40 (patch) | |
tree | 79fc81642a660011ea2192e3a27b0c1d66fa330d | |
parent | 4df341b0410d016f4f36d5ea92f36c8c7028a696 (diff) | |
parent | 6a6a6f36707f9588249990eb2d67e414d2eebd38 (diff) | |
download | CMake-a4e0bba98770094050cad5cf337eae4246ce0f40.zip CMake-a4e0bba98770094050cad5cf337eae4246ce0f40.tar.gz CMake-a4e0bba98770094050cad5cf337eae4246ce0f40.tar.bz2 |
Merge topic 'avoid-undefined-behavior'
6a6a6f3 libarchive: fixed undefined left shift with signed ints
-rw-r--r-- | Utilities/cmlibarchive/libarchive/archive_endian.h | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/Utilities/cmlibarchive/libarchive/archive_endian.h b/Utilities/cmlibarchive/libarchive/archive_endian.h index bbf58fd..3c039f7 100644 --- a/Utilities/cmlibarchive/libarchive/archive_endian.h +++ b/Utilities/cmlibarchive/libarchive/archive_endian.h @@ -64,7 +64,13 @@ archive_be16dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[0] << 8) | p[1]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 8) | p1); } static inline uint32_t @@ -72,7 +78,15 @@ archive_be32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p3 = p[3]; + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p0 << 24) | (p1 << 16) | (p2 << 8) | p3); } static inline uint64_t @@ -88,7 +102,13 @@ archive_le16dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[1] << 8) | p[0]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p1 << 8) | p0); } static inline uint32_t @@ -96,7 +116,15 @@ archive_le32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; - return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); + /* Store into unsigned temporaries before left shifting, to avoid + promotion to signed int and then left shifting into the sign bit, + which is undefined behaviour. */ + unsigned int p3 = p[3]; + unsigned int p2 = p[2]; + unsigned int p1 = p[1]; + unsigned int p0 = p[0]; + + return ((p3 << 24) | (p2 << 16) | (p1 << 8) | p0); } static inline uint64_t |