]> The Tcpdump Group git mirrors - libpcap/commitdiff
Fix the "|" and "&" operators of the "byte" primitive.
authorDenis Ovsienko <[email protected]>
Thu, 27 Mar 2025 17:23:37 +0000 (17:23 +0000)
committerDenis Ovsienko <[email protected]>
Thu, 27 Mar 2025 20:37:43 +0000 (20:37 +0000)
In gen_byteop() the "=", "<" and ">" cases load the required packet byte
into the A register implicitly via gen_load_a(), but the other two cases
need to do it explicitly, otherwise A will hold the previous value and
the ALU instruction will take that as the input.

The bug was introduced in the tcpdump 2.0 release (January 1991, before
libpcap 0.0), which replaced filter.c with gencode.c.

CHANGES
gencode.c
testprogs/TESTrun

diff --git a/CHANGES b/CHANGES
index 6b817127226631e44a7011833ba5f502234695ac..ecf7f49a28e20b6183cfc75c0d77cec59ca872ae 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -56,6 +56,7 @@ DayOfTheWeek, Month DD, YYYY / The Tcpdump Group
       Require "(iso|isis) proto" values to be within valid ranges.
       Use the correct IS-IS PDU type offset for DLT_C_HDLC.
       Use the correct bit mask for IS-IS PDU type value.
+      Fix the "|" and "&" operators of the "byte" primitive.
     rpcap:
       Support user names and passwords in rpcap:// and rpcaps:// URLs.
       Add a -t flag to rpcapd to specify the data channel port; from
index 520277ba7e43e1a38f5d68857a046cdacf1aa9db..40614b93dc34f6c886e546855ebba94a9977dda5 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -8147,8 +8147,11 @@ gen_byteop(compiler_state_t *cstate, int op, int idx, bpf_u_int32 val)
                break;
        }
        s->s.k = val;
+       // Load the required byte first.
+       struct slist *s0 = gen_load_a(cstate, OR_LINKHDR, idx, BPF_B);
+       sappend(s0, s);
        b = new_block(cstate, JMP(BPF_JEQ));
-       b->stmts = s;
+       b->stmts = s0;
        gen_not(b);
 
        return b;
index 92d1b78852b1167380b5fa8d4d271939919418f0..5ca0d7a37823df8d5e84f5c1f5b6d776c3124646 100755 (executable)
@@ -10664,10 +10664,11 @@ my @accept_blocks = (
                DLT => 'IPV4',
                aliases => ['byte 8 | 5'],
                unopt => '
-                       (000) or       #0x5
-                       (001) jeq      #0x0             jt 2    jf 3
-                       (002) ret      #0
-                       (003) ret      #262144
+                       (000) ldb      [8]
+                       (001) or       #0x5
+                       (002) jeq      #0x0             jt 3    jf 4
+                       (003) ret      #0
+                       (004) ret      #262144
                        ',
        }, # byte_or
        {
@@ -10675,10 +10676,11 @@ my @accept_blocks = (
                DLT => 'IPV4',
                aliases => ['byte 8 & 5'],
                unopt => '
-                       (000) and      #0x5
-                       (001) jeq      #0x0             jt 2    jf 3
-                       (002) ret      #0
-                       (003) ret      #262144
+                       (000) ldb      [8]
+                       (001) and      #0x5
+                       (002) jeq      #0x0             jt 3    jf 4
+                       (003) ret      #0
+                       (004) ret      #262144
                        ',
        }, # byte_and
 );