]> The Tcpdump Group git mirrors - libpcap/commitdiff
Use the EXTRACT_ macros to extract big-endian integers from a buffer.
authorGuy Harris <[email protected]>
Tue, 16 Oct 2018 22:41:35 +0000 (15:41 -0700)
committerGuy Harris <[email protected]>
Tue, 16 Oct 2018 22:41:35 +0000 (15:41 -0700)
This:

1) makes it a bit clearer what the code is doing;

2) means that on platforms that support unaligned accesses, the
generated code involves fewer instructions;

3) squelches an undefined behavior warning from shifting an int value
left 24 bits (in practice, it works, but...).

Also, note that we do too much signed integer stuff here.

Credit to OSS-Fuzz for finding the undefined behavior issue.

gencode.c

index 3f528fa2230b309575cf959687d5244921a63392..51adc328f799f7bc26a099c662adb6efca0614e7 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -50,6 +50,8 @@
 
 #include "pcap-int.h"
 
+#include "extract.h"
+
 #include "ethertype.h"
 #include "nlpid.h"
 #include "llc.h"
@@ -975,13 +977,22 @@ gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
 {
        register struct block *b, *tmp;
 
+       /*
+        * XXX - the actual *instructions* do unsigned comparisons on
+        * most platforms, and the load instructions don't do sign
+        * extension, so gen_cmp() should really take an unsigned
+        * value argument.
+        *
+        * As the load instructons also don't do sign-extension, we
+        * fetch the values from the byte array as unsigned.  We don't
+        * want to use the signed versions of the extract calls.
+        */
        b = NULL;
        while (size >= 4) {
                register const u_char *p = &v[size - 4];
-               bpf_int32 w = ((bpf_int32)p[0] << 24) |
-                   ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
 
-               tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w);
+               tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W,
+                   (bpf_int32)EXTRACT_BE_U_4(p));
                if (b != NULL)
                        gen_and(b, tmp);
                b = tmp;
@@ -989,9 +1000,9 @@ gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
        }
        while (size >= 2) {
                register const u_char *p = &v[size - 2];
-               bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
 
-               tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w);
+               tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H,
+                   (bpf_int32)EXTRACT_BE_U_2(p));
                if (b != NULL)
                        gen_and(b, tmp);
                b = tmp;