diff --git a/0611-With-MSVC-abort-if-_BitScanForward-returns-0.patch b/0611-With-MSVC-abort-if-_BitScanForward-returns-0.patch new file mode 100644 index 0000000000000000000000000000000000000000..c76637ff2c8fc52de6e9ed936d30c146c874cc74 --- /dev/null +++ b/0611-With-MSVC-abort-if-_BitScanForward-returns-0.patch @@ -0,0 +1,31 @@ +From 3b9b6100912f7bb1ee43f9cfb51e804765a37bd4 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Thu, 3 Oct 2019 09:27:36 -0700 +Subject: [PATCH 611/977] With MSVC, abort if _BitScanForward() returns 0. + +It should never return zero, as never pass a value of 0 to +lowest_set_bit(), but this should keep Coverity from getting upset (as a +result of not understanding _BitScanForward() well enough to realize +that if it's passed a non-zero value it will never return 0). + +Reported by Charles Smith at Tangible Security. +--- + optimize.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/optimize.c b/optimize.c +index 283a6de..e38d2d7 100644 +--- a/optimize.c ++++ b/optimize.c +@@ -137,7 +137,7 @@ lowest_set_bit(int mask) + * (It's currently not, in MSVC, even on 64-bit platforms, but....) + */ + if (_BitScanForward(&bit, (unsigned int)mask) == 0) +- return -1; /* mask is zero */ ++ abort(); /* mask is zero */ + return (int)bit; + } + #elif defined(MSDOS) && defined(__DJGPP__) +-- +1.8.3.1 + diff --git a/0875-optimize-make-some-variables-unsigned.patch b/0875-optimize-make-some-variables-unsigned.patch new file mode 100644 index 0000000000000000000000000000000000000000..b406aaa293e77541a0a3ddaf12218bd0620f73bb --- /dev/null +++ b/0875-optimize-make-some-variables-unsigned.patch @@ -0,0 +1,279 @@ +From d71913d38475f5b4f0dc753074337ba29d5c0789 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Thu, 21 May 2020 22:37:19 -0700 +Subject: [PATCH 875/977] optimize: make some variables unsigned. + +That should avoid some overflow failure modes, and allow saner overflow +checking. +--- + optimize.c | 92 ++++++++++++++++++++++++++++++++++++++------------------------ + 1 file changed, 57 insertions(+), 35 deletions(-) + +diff --git a/optimize.c b/optimize.c +index 325d4ff..bea8cdc 100644 +--- a/optimize.c ++++ b/optimize.c +@@ -115,7 +115,7 @@ pcap_set_print_dot_graph(int value) + /* + * GCC 3.4 and later; we have __builtin_ctz(). + */ +- #define lowest_set_bit(mask) __builtin_ctz(mask) ++ #define lowest_set_bit(mask) ((u_int)__builtin_ctz(mask)) + #elif defined(_MSC_VER) + /* + * Visual Studio; we support only 2005 and later, so use +@@ -127,7 +127,7 @@ pcap_set_print_dot_graph(int value) + #pragma intrinsic(_BitScanForward) + #endif + +-static __forceinline int ++static __forceinline u_int + lowest_set_bit(int mask) + { + unsigned long bit; +@@ -138,14 +138,14 @@ lowest_set_bit(int mask) + */ + if (_BitScanForward(&bit, (unsigned int)mask) == 0) + abort(); /* mask is zero */ +- return (int)bit; ++ return (u_int)bit; + } + #elif defined(MSDOS) && defined(__DJGPP__) + /* + * MS-DOS with DJGPP, which declares ffs() in , which + * we've already included. + */ +- #define lowest_set_bit(mask) (ffs((mask)) - 1) ++ #define lowest_set_bit(mask) ((u_int)(ffs((mask)) - 1)) + #elif (defined(MSDOS) && defined(__WATCOMC__)) || defined(STRINGS_H_DECLARES_FFS) + /* + * MS-DOS with Watcom C, which has and declares ffs() there, +@@ -153,18 +153,18 @@ lowest_set_bit(int mask) + * of the Single UNIX Specification). + */ + #include +- #define lowest_set_bit(mask) (ffs((mask)) - 1) ++ #define lowest_set_bit(mask) (u_int)((ffs((mask)) - 1)) + #else + /* + * None of the above. + * Use a perfect-hash-function-based function. + */ +-static int ++static u_int + lowest_set_bit(int mask) + { + unsigned int v = (unsigned int)mask; + +- static const int MultiplyDeBruijnBitPosition[32] = { ++ static const u_int MultiplyDeBruijnBitPosition[32] = { + 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, + 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9 + }; +@@ -257,17 +257,17 @@ typedef struct { + */ + int done; + +- int n_blocks; ++ u_int n_blocks; /* number of blocks in the CFG; guaranteed to be > 0, as it's a RET instruction at a minimum */ + struct block **blocks; +- int n_edges; ++ u_int n_edges; /* twice n_blocks, so guaranteed to be > 0 */ + struct edge **edges; + + /* + * A bit vector set representation of the dominators. + * We round up the set size to the next power of two. + */ +- int nodewords; +- int edgewords; ++ u_int nodewords; /* number of 32-bit words for a bit vector of "number of nodes" bits; guaranteed to be > 0 */ ++ u_int edgewords; /* number of 32-bit words for a bit vector of "number of edges" bits; guaranteed to be > 0 */ + struct block **levels; + bpf_u_int32 *space; + +@@ -292,32 +292,35 @@ typedef struct { + + /* + * a := a intersect b ++ * n must be guaranteed to be > 0 + */ + #define SET_INTERSECT(a, b, n)\ + {\ + register bpf_u_int32 *_x = a, *_y = b;\ +- register int _n = n;\ +- while (--_n >= 0) *_x++ &= *_y++;\ ++ register u_int _n = n;\ ++ do *_x++ &= *_y++; while (--_n != 0);\ + } + + /* + * a := a - b ++ * n must be guaranteed to be > 0 + */ + #define SET_SUBTRACT(a, b, n)\ + {\ + register bpf_u_int32 *_x = a, *_y = b;\ +- register int _n = n;\ +- while (--_n >= 0) *_x++ &=~ *_y++;\ ++ register u_int _n = n;\ ++ do *_x++ &=~ *_y++; while (--_n != 0);\ + } + + /* + * a := a union b ++ * n must be guaranteed to be > 0 + */ + #define SET_UNION(a, b, n)\ + {\ + register bpf_u_int32 *_x = a, *_y = b;\ +- register int _n = n;\ +- while (--_n >= 0) *_x++ |= *_y++;\ ++ register u_int _n = n;\ ++ do *_x++ |= *_y++; while (--_n != 0);\ + } + + uset all_dom_sets; +@@ -414,7 +417,8 @@ find_levels(opt_state_t *opt_state, struct icode *ic) + static void + find_dom(opt_state_t *opt_state, struct block *root) + { +- int i; ++ u_int i; ++ int level; + struct block *b; + bpf_u_int32 *x; + +@@ -422,16 +426,25 @@ find_dom(opt_state_t *opt_state, struct block *root) + * Initialize sets to contain all nodes. + */ + x = opt_state->all_dom_sets; ++ /* ++ * These are both guaranteed to be > 0, so the product is ++ * guaranteed to be > 0. ++ * ++ * XXX - but what if it overflows? ++ */ + i = opt_state->n_blocks * opt_state->nodewords; +- while (--i >= 0) ++ do + *x++ = 0xFFFFFFFFU; ++ while (--i != 0); + /* Root starts off empty. */ +- for (i = opt_state->nodewords; --i >= 0;) ++ i = opt_state->nodewords; ++ do + root->dom[i] = 0; ++ while (--i != 0); + + /* root->level is the highest level no found. */ +- for (i = root->level; i >= 0; --i) { +- for (b = opt_state->levels[i]; b; b = b->link) { ++ for (level = root->level; level >= 0; --level) { ++ for (b = opt_state->levels[level]; b; b = b->link) { + SET_INSERT(b->dom, b->id); + if (JT(b) == 0) + continue; +@@ -458,19 +471,28 @@ propedom(opt_state_t *opt_state, struct edge *ep) + static void + find_edom(opt_state_t *opt_state, struct block *root) + { +- int i; ++ u_int i; + uset x; ++ int level; + struct block *b; + + x = opt_state->all_edge_sets; +- for (i = opt_state->n_edges * opt_state->edgewords; --i >= 0; ) ++ /* ++ * These are both guaranteed to be > 0, so the product is ++ * guaranteed to be > 0. ++ * ++ * XXX - but what if it overflows? ++ */ ++ i = opt_state->n_edges * opt_state->edgewords; ++ do + x[i] = 0xFFFFFFFFU; ++ while (--i != 0); + + /* root->level is the highest level no found. */ + memset(root->et.edom, 0, opt_state->edgewords * sizeof(*(uset)0)); + memset(root->ef.edom, 0, opt_state->edgewords * sizeof(*(uset)0)); +- for (i = root->level; i >= 0; --i) { +- for (b = opt_state->levels[i]; b != 0; b = b->link) { ++ for (level = root->level; level >= 0; --level) { ++ for (b = opt_state->levels[level]; b != 0; b = b->link) { + propedom(opt_state, &b->et); + propedom(opt_state, &b->ef); + } +@@ -487,7 +509,7 @@ find_edom(opt_state_t *opt_state, struct block *root) + static void + find_closure(opt_state_t *opt_state, struct block *root) + { +- int i; ++ int level; + struct block *b; + + /* +@@ -497,8 +519,8 @@ find_closure(opt_state_t *opt_state, struct block *root) + opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->all_closure_sets)); + + /* root->level is the highest level no found. */ +- for (i = root->level; i >= 0; --i) { +- for (b = opt_state->levels[i]; b; b = b->link) { ++ for (level = root->level; level >= 0; --level) { ++ for (b = opt_state->levels[level]; b; b = b->link) { + SET_INSERT(b->closure, b->id); + if (JT(b) == 0) + continue; +@@ -1674,6 +1696,6 @@ fold_edge(struct block *child, struct edge *ep) + static void + opt_j(opt_state_t *opt_state, struct edge *ep) + { +- register int i, k; ++ register u_int i, k; + register struct block *target; + +@@ -2116,17 +2138,16 @@ link_inedge(struct edge *parent, struct block *child) + static void + find_inedges(opt_state_t *opt_state, struct block *root) + { +- int i; + struct block *b; + +- for (i = 0; i < opt_state->n_blocks; ++i) ++ for (u_int i = 0; i < opt_state->n_blocks; ++i) + opt_state->blocks[i]->in_edges = 0; + + /* + * Traverse the graph, adding each edge to the predecessor + * list of its successors. Skip the leaves (i.e. level 0). + */ +- for (i = root->level; i > 0; --i) { ++ for (int i = root->level; i > 0; --i) { + for (b = opt_state->levels[i]; b != 0; b = b->link) { + link_inedge(&b->et, JT(b)); + link_inedge(&b->ef, JF(b)); +@@ -2336,7 +2357,7 @@ static void + intern_blocks(opt_state_t *opt_state, struct icode *ic) + { + struct block *p; +- int i, j; ++ u_int i, j; + int done1; /* don't shadow global */ + top: + done1 = 1; +@@ -2345,7 +2366,8 @@ intern_blocks(opt_state_t *opt_state, struct icode *ic) + + mark_code(ic); + +- for (i = opt_state->n_blocks - 1; --i >= 0; ) { ++ for (i = opt_state->n_blocks - 1; i != 0; ) { ++ --i; + if (!isMarked(ic, opt_state->blocks[i])) + continue; + for (j = i + 1; j < opt_state->n_blocks; ++j) { +-- +1.8.3.1 + diff --git a/0876-optimize-fix-some-of-those-changes.patch b/0876-optimize-fix-some-of-those-changes.patch new file mode 100644 index 0000000000000000000000000000000000000000..ad63e983e762a6b76c8df6278897bffbf8608004 --- /dev/null +++ b/0876-optimize-fix-some-of-those-changes.patch @@ -0,0 +1,96 @@ +From 2aa7d268e2ce37025d68a3f428001f6f779f56e8 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Thu, 21 May 2020 23:36:09 -0700 +Subject: [PATCH 876/977] optimize: fix some of those changes. + +For loops with predecrements that we eliminated because we don't want to +rely on the loop index going negative if it's zero before the +predecrement - the index is now unsigned, so it'll *never go negative - +we revert to a similar loop, but with the test checking whether the +index is 0 and decrementing it as the first action in the loop body. + +(Yeah, it means that, on machines with condition codes, you don't get to +use the condition code setting of the decrement "for free"; we'll let +the compiler and the processor figure out how to do that efficiently.) +--- + optimize.c | 35 ++++++++++++++++------------------- + 1 file changed, 16 insertions(+), 19 deletions(-) + +diff --git a/optimize.c b/optimize.c +index bea8cdc..07fc0f3 100644 +--- a/optimize.c ++++ b/optimize.c +@@ -427,20 +427,18 @@ find_dom(opt_state_t *opt_state, struct block *root) + */ + x = opt_state->all_dom_sets; + /* +- * These are both guaranteed to be > 0, so the product is +- * guaranteed to be > 0. +- * +- * XXX - but what if it overflows? ++ * XXX - what if the multiplication overflows? + */ + i = opt_state->n_blocks * opt_state->nodewords; +- do ++ while (i != 0) { ++ --i; + *x++ = 0xFFFFFFFFU; +- while (--i != 0); ++ } + /* Root starts off empty. */ +- i = opt_state->nodewords; +- do ++ for (i = opt_state->nodewords; i != 0;) { ++ --i; + root->dom[i] = 0; +- while (--i != 0); ++ } + + /* root->level is the highest level no found. */ + for (level = root->level; level >= 0; --level) { +@@ -478,15 +476,12 @@ find_edom(opt_state_t *opt_state, struct block *root) + + x = opt_state->all_edge_sets; + /* +- * These are both guaranteed to be > 0, so the product is +- * guaranteed to be > 0. +- * +- * XXX - but what if it overflows? ++ * XXX - what if the multiplication overflows? + */ +- i = opt_state->n_edges * opt_state->edgewords; +- do ++ for (i = opt_state->n_edges * opt_state->edgewords; i != 0; ) { ++ --i; + x[i] = 0xFFFFFFFFU; +- while (--i != 0); ++ } + + /* root->level is the highest level no found. */ + memset(root->et.edom, 0, opt_state->edgewords * sizeof(*(uset)0)); +@@ -2138,17 +2133,19 @@ link_inedge(struct edge *parent, struct block *child) + static void + find_inedges(opt_state_t *opt_state, struct block *root) + { ++ u_int i; ++ int level; + struct block *b; + +- for (u_int i = 0; i < opt_state->n_blocks; ++i) ++ for (i = 0; i < opt_state->n_blocks; ++i) + opt_state->blocks[i]->in_edges = 0; + + /* + * Traverse the graph, adding each edge to the predecessor + * list of its successors. Skip the leaves (i.e. level 0). + */ +- for (int i = root->level; i > 0; --i) { +- for (b = opt_state->levels[i]; b != 0; b = b->link) { ++ for (level = root->level; level > 0; --level) { ++ for (b = opt_state->levels[level]; b != 0; b = b->link) { + link_inedge(&b->et, JT(b)); + link_inedge(&b->ef, JF(b)); + } +-- +1.8.3.1 + diff --git a/libpcap.spec b/libpcap.spec index 61d674337ff138aedacf3c8c873b330478d2e361..be61c9f6e2f2fddd88ead37e6453df1253722301 100644 --- a/libpcap.spec +++ b/libpcap.spec @@ -1,15 +1,18 @@ Name: libpcap Epoch: 14 Version: 1.9.1 -Release: 5 +Release: 6 Summary: A system-independent interface for user-level packet capture License: BSD with advertising URL: http://www.tcpdump.org Source0: http://www.tcpdump.org/release/%{name}-%{version}.tar.gz -Patch0001: 0003-pcap-linux-apparently-ctc-interfaces-on-s390-has-eth.patch -Patch0002: clean-up-signed-vs-unsigned-do-more-error-checking-in-the-parser.patch -Patch0003: fix-optimize-add-a-bunch-of-overflow-checks.patch +Patch0: 0003-pcap-linux-apparently-ctc-interfaces-on-s390-has-eth.patch +Patch1: clean-up-signed-vs-unsigned-do-more-error-checking-in-the-parser.patch +Patch2: fix-optimize-add-a-bunch-of-overflow-checks.patch +Patch3: 0611-With-MSVC-abort-if-_BitScanForward-returns-0.patch +Patch4: 0875-optimize-make-some-variables-unsigned.patch +Patch5: 0876-optimize-fix-some-of-those-changes.patch BuildRequires: bison bluez-libs-devel flex gcc git glibc-kernheaders >= 2.2.0 @@ -60,6 +63,12 @@ export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %{_mandir}/man* %changelog +* Fri Aug 07 2020 lunankun - 14:1.9.1-6 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix overflow in opt_init + * Tue May 26 2020 gaihuiying - 14:1.9.1-5 - Type:bugfix - ID:NA