summaryrefslogtreecommitdiff
path: root/lib/stream.h
diff options
context:
space:
mode:
authorDaniel Walton <dwalton76@gmail.com>2017-09-12 17:48:03 -0400
committerGitHub <noreply@github.com>2017-09-12 17:48:03 -0400
commite775854d9c87fc3dd163559b344f50b2acf4d562 (patch)
tree72b04b908620fcd1fd70ac849558c353c32b2be9 /lib/stream.h
parent016bded5d504dec6af791cb468e7b316a52af05a (diff)
parent937652c6e43fc74ba969bbace475bdf929cdc5d0 (diff)
Merge pull request #1133 from opensourcerouting/shift-sign
*: fix be32 reading / 24-bit left shift
Diffstat (limited to 'lib/stream.h')
-rw-r--r--lib/stream.h18
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/stream.h b/lib/stream.h
index 33dd64c4a3..7dcdca69f6 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -239,4 +239,22 @@ extern struct stream *stream_fifo_head(struct stream_fifo *fifo);
extern void stream_fifo_clean(struct stream_fifo *fifo);
extern void stream_fifo_free(struct stream_fifo *fifo);
+/* This is here because "<< 24" is particularly problematic in C.
+ * This is because the left operand of << is integer-promoted, which means
+ * an uint8_t gets converted into a *signed* int. Shifting into the sign
+ * bit of a signed int is theoretically undefined behaviour, so - the left
+ * operand needs to be cast to unsigned.
+ *
+ * This is not a problem for 16- or 8-bit values (they don't reach the sign
+ * bit), for 64-bit values (you need to cast them anyway), and neither for
+ * encoding (because it's downcasted.)
+ */
+static inline uint8_t *ptr_get_be32(uint8_t *ptr, uint32_t *out)
+{
+ uint32_t tmp;
+ memcpy(&tmp, ptr, sizeof(tmp));
+ *out = ntohl(tmp);
+ return ptr + 4;
+}
+
#endif /* _ZEBRA_STREAM_H */