From 20266d9bb93c699b0936027ce08a95f10f0bacf0 Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Wed, 8 Jul 2026 19:12:08 +0000 Subject: [PATCH] =?UTF-8?q?=EC=95=88=EB=85=95=ED=95=98=EC=84=B8=EC=9A=94!?= =?UTF-8?q?=20=EC=97=AC=EB=9F=AC=EB=B6=84=EC=9D=98=20AI=20=EC=BD=94?= =?UTF-8?q?=EB=94=A9=20=EC=97=90=EC=9D=B4=EC=A0=84=ED=8A=B8=20Jules?= =?UTF-8?q?=EC=9E=85=EB=8B=88=EB=8B=A4.=20=F0=9F=9B=A1=EF=B8=8F=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=20=EA=B2=80=EC=83=89=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=EC=9D=98=20=EB=B6=80=EC=A0=95=EC=A0=81=EC=9D=B8=20?= =?UTF-8?q?=EC=A1=B0=ED=95=A9=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=B4=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=ED=95=98=EB=8A=94=20=EC=B9=98=EB=AA=85?= =?UTF-8?q?=EC=A0=81=EC=9D=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EB=AC=B4?= =?UTF-8?q?=EA=B2=B0=EC=84=B1=20=EC=86=90=EC=8B=A4=20=EC=B7=A8=EC=95=BD?= =?UTF-8?q?=EC=A0=90=EC=9D=84=20=EB=B0=A9=EA=B8=88=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=95=98=EC=97=AC=20=EC=95=88=EB=82=B4=ED=95=B4=20=EB=93=9C?= =?UTF-8?q?=EB=A6=BD=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 기존 코드에서는 매치되는 항목이 없을 경우 빈 인덱스(`integer(0)`)를 반환하는 패턴 검색 함수를 `c()`로 묶어 벡터 인덱싱에서 제외(`-c(...)`)하려고 할 때, 의도치 않게 전체 벡터가 삭제되어 `character(0)`이 반환되는 치명적인 결함이 있었습니다. 이로 인해 파라미터 리스트(`IPDParmNames`)가 비워지면서 후속 로직에 오류를 유발할 수 있었습니다. 이 취약점을 해결하기 위해 인덱스 대신 논리값(True/False)을 반환하는 패턴 매칭 함수를 사용하는 방식으로 코드를 리팩토링했습니다. 여러 정규표현식을 하나로 결합하여 부정 매칭(예: `"^(MEAN|COV|ak|d0$)"` 패턴이 아닌 것을 필터링)을 수행하도록 변경했으며, 이를 통해 매치 결과가 없을 때도 벡터가 정상적으로 보존되도록 안전하게 개선했습니다. 이와 함께 해당 취약점에 대한 분석과 향후 예방 지침을 `.jules/sentinel.md` 저널에 꼼꼼히 기록해 두었습니다. 수정된 사항과 관련하여 궁금한 점이 있으시다면 언제든 말씀해 주세요! --- .jules/sentinel.md | 6 ++++++ R/aFIPC.R | 9 +-------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.jules/sentinel.md b/.jules/sentinel.md index 75b4a40..ea52ddb 100644 --- a/.jules/sentinel.md +++ b/.jules/sentinel.md @@ -17,3 +17,9 @@ 1. Always replace `while (!exists(...))` retries with a bounded `for` loop (e.g., `for (attempt in seq_len(3))`). 2. Include an explicit check for the success condition inside the loop (`if (exists('model')) break`). 3. After the loop, verify success and fail securely with an explicit error (`if (!exists('model')) stop(...)`) to prevent unhandled exceptions downstream. + +## 2024-07-08 - Data Integrity Loss via Negative Grep Combination +**Vulnerability:** Filtering vectors in base R using a combination of negative `grep()` results, such as `x[-c(grep("A", x), grep("B", x))]`, wiped out the entire vector when no matches were found. This evaluates to `x[-integer(0)]` which incorrectly returns `character(0)` instead of the original vector, causing unexpected data loss and potentially breaking downstream logic that relies on preserved vectors. +**Learning:** Avoid using `grep()` combinations with negative indexing for filtering vectors unless strictly checked. Empty match results do not map to "ignore" in vector exclusions. +**Prevention:** +Always replace `x[-c(grep(pattern1, x), grep(pattern2, x))]` logic with `x[!grepl("(pattern1|pattern2)", x)]`. The `grepl()` function returns a robust logical vector where `FALSE` can be reliably negated, keeping the vector intact when no elements match. diff --git a/R/aFIPC.R b/R/aFIPC.R index 2e5ac4a..45a64a1 100644 --- a/R/aFIPC.R +++ b/R/aFIPC.R @@ -604,14 +604,7 @@ autoFIPC <- IPDParmNames <- OldScaleParms$name IPDParmNames <- IPDParmNames[!duplicated(IPDParmNames)] IPDParmNames <- - IPDParmNames[ - -c( - grep("^MEAN", IPDParmNames), - grep("^COV", IPDParmNames), - grep("^ak", IPDParmNames), - grep("^d0$", IPDParmNames) - ) - ] + IPDParmNames[!grepl("^(MEAN|COV|ak|d0$)", IPDParmNames)] IPDParmNames <- as.character(IPDParmNames) mirt::mirtCluster()