nmap-0002: nmap.cc merge_port_lists O(N²) port dedup → unordered_set O(N); ~65000x at max range haproxy-0004: http_ana.c http_capture_headers O(H×C) cap_hdr walk per request → pre-built HashMap O(H) nginx-0004: ngx_http_upstream_keepalive_module.c keepalive_get_peer O(C) sockaddr scan per upstream request → HashMap O(1) weechat-0003: irc-channel.c irc_channel_search O(C) linked-list scan per message handler → channels_hashtable O(1) zeek-0002: Attr.cc Attributes::AddAttrs O(A²) triple-Find/RemoveAttr per attr → unordered_map index O(A) curl-0004: mime.c search_header O(P×H) 3x per part per mime_add_headers → pre-indexed header name set O(P)
69 lines
2.3 KiB
Diff
69 lines
2.3 KiB
Diff
--- a/libavcodec/gif.c
|
||
+++ b/libavcodec/gif.c
|
||
@@ -67,18 +67,53 @@ static void shrink_palette(const uint32_t *src, uint8_t *map,
|
||
uint32_t *dst, size_t *palette_count)
|
||
{
|
||
- size_t colors_seen = 0;
|
||
-
|
||
- for (size_t i = 0; i < AVPALETTE_COUNT; i++) {
|
||
- int seen = 0;
|
||
- for (size_t c = 0; c < colors_seen; c++) {
|
||
- if (src[i] == dst[c]) {
|
||
- seen = 1;
|
||
- break;
|
||
- }
|
||
- }
|
||
- if (!seen) {
|
||
- dst[colors_seen] = src[i];
|
||
- map[i] = colors_seen;
|
||
- colors_seen++;
|
||
- }
|
||
- }
|
||
-
|
||
- *palette_count = colors_seen;
|
||
+ /*
|
||
+ * CWE-407 fix: replace O(P²) nested scan with an open-addressing hash
|
||
+ * table over the 256-entry colour space.
|
||
+ *
|
||
+ * Original: for each of P=256 entries, scan all previously-seen entries →
|
||
+ * O(0+1+…+255) = 32,640 comparisons worst-case per frame.
|
||
+ *
|
||
+ * Fix: Knuth multiplicative hash folds 32-bit ARGB to an 8-bit slot;
|
||
+ * linear probing resolves collisions. Total work: O(P) = 256 hash ops.
|
||
+ * Speedup: ~127× worst-case (all 256 colours unique).
|
||
+ *
|
||
+ * Sentinel: 0xFFFFFFFF (fully-opaque white BGRA). A separate occupied[]
|
||
+ * boolean array guards against false-hit on the sentinel value.
|
||
+ */
|
||
+ uint32_t seen_color[AVPALETTE_COUNT];
|
||
+ uint8_t seen_slot[AVPALETTE_COUNT];
|
||
+ uint8_t occupied[AVPALETTE_COUNT];
|
||
+ size_t colors_seen = 0;
|
||
+
|
||
+ memset(occupied, 0, sizeof(occupied));
|
||
+
|
||
+ for (size_t i = 0; i < AVPALETTE_COUNT; i++) {
|
||
+ uint32_t color = src[i];
|
||
+ /* Knuth multiplicative hash → 8-bit bucket index */
|
||
+ size_t h = (size_t)((color * 2654435761UL) >> 24) & 0xFF;
|
||
+
|
||
+ /* Linear-probe open-addressing lookup */
|
||
+ while (occupied[h] && seen_color[h] != color)
|
||
+ h = (h + 1) & 0xFF;
|
||
+
|
||
+ if (occupied[h]) {
|
||
+ /* colour already in hash table: reuse its dst slot */
|
||
+ map[i] = seen_slot[h];
|
||
+ } else {
|
||
+ /* new colour: insert into hash table and dst[] */
|
||
+ occupied[h] = 1;
|
||
+ seen_color[h] = color;
|
||
+ seen_slot[h] = (uint8_t)colors_seen;
|
||
+ dst[colors_seen] = color;
|
||
+ map[i] = (uint8_t)colors_seen;
|
||
+ colors_seen++;
|
||
+ }
|
||
+ }
|
||
+
|
||
+ *palette_count = colors_seen;
|
||
}
|