java-topology/defects/dosbox-x-0003/patch/dosbox-x-0003-jtbs-dbox-vector-find-in-nested-loop.patch

46 lines
3 KiB
Diff

# UNDF: UNDF-2026-000001084
--- a/src/hardware/vga_draw.cpp
+++ b/src/hardware/vga_draw.cpp
@@ -2585 +2585 @@
-std::vector<std::pair<int,int>> jtbs = {}, dbox = {};
+std::unordered_set<uint32_t> jtbs_set, dbox_set;
+static inline uint32_t encode_pos(int row, int col) { return ((uint32_t)(uint16_t)row << 16) | (uint32_t)(uint16_t)col; }
@@ -2622,2 +2622,2 @@
- if (!jtbs.empty()) jtbs.erase(std::remove_if(jtbs.begin(), jtbs.end(), first_equal(row)), jtbs.end());
- if (!dbox.empty()) dbox.erase(std::remove_if(dbox.begin(), dbox.end(), first_equal(row)), dbox.end());
+ for (auto it = jtbs_set.begin(); it != jtbs_set.end(); ) { if ((int)(*it >> 16) == row) it = jtbs_set.erase(it); else ++it; }
+ for (auto it = dbox_set.begin(); it != dbox_set.end(); ) { if ((int)(*it >> 16) == row) it = dbox_set.erase(it); else ++it; }
@@ -2686 +2686 @@
- if (line == 1) dbox.push_back(std::make_pair(row, col));
+ if (line == 1) dbox_set.insert(encode_pos(row, col));
@@ -2722 +2722 @@
- if (line == 1) jtbs.push_back(std::make_pair(row, col));
+ if (line == 1) jtbs_set.insert(encode_pos(row, col));
--- a/src/ints/mouse.cpp
+++ b/src/ints/mouse.cpp
@@ -995 +995 @@
-extern std::vector<std::pair<int,int>> jtbs, dbox;
+extern std::unordered_set<uint32_t> jtbs_set, dbox_set;
+static inline bool jtbs_has(int row, int col) { return jtbs_set.count(((uint32_t)(uint16_t)row << 16) | (uint32_t)(uint16_t)col) != 0; }
+static inline bool dbox_has(int row, int col) { return dbox_set.count(((uint32_t)(uint16_t)row << 16) | (uint32_t)(uint16_t)col) != 0; }
@@ -1116 +1116 @@
- && showdbcs) ? std::find(jtbs.begin(), jtbs.end(), std::make_pair(i,j)) != jtbs.end():false;
+ && showdbcs) ? jtbs_has(i,j) : false;
@@ -1130 +1130 @@
- && showdbcs && std::find(dbox.begin(), dbox.end(), std::make_pair(i,j)) != dbox.end()) bdlist.push_back(len);
+ && showdbcs && dbox_has(i,j)) bdlist.push_back(len);
@@ -1138 +1138 @@
- && showdbcs))&&j==c2&&c2<c-1&&std::find(jtbs.begin(), jtbs.end(), std::make_pair(i,j+1)) != jtbs.end()) {
+ && showdbcs))&&j==c2&&c2<c-1&&jtbs_has(i,j+1)) {
#
# CWE-407: Mouse_GetSelected scans jtbs/dbox (vector<pair<int,int>>) with
# std::find inside nested loops over screen rows (i) and columns (j).
# For a full 80x25 DBCS screen, jtbs can hold ~2000 entries. Each of the
# ~2000 (row, col) positions calls std::find → O(rows * cols * N_entries)
# = O(N²) where N = number of DBCS characters on screen.
# Fix: replace vector<pair<int,int>> with unordered_set<uint32_t> using
# (row<<16)|col encoding. Membership test drops from O(N) to O(1).
# The row-based erase loop replaces erase(remove_if) — same O(N) cost,
# called only on scanline invalidation, not per text-selection character.
# Severity: MEDIUM — triggered during mouse text selection/copy in DBCS
# (Japanese/Chinese/Korean) codepage mode; scales with screen DBCS content.