Skip to content

[GFX-591] 去除 IllegalWordDetection 的 unsafe 指针并拆分 DetectIllegalWords 消除 Sonar S6640 与 S3776 - #368

Merged
github-actions[bot] merged 2 commits into
mainfrom
feature/gfx-591
Aug 7, 2026
Merged

[GFX-591] 去除 IllegalWordDetection 的 unsafe 指针并拆分 DetectIllegalWords 消除 Sonar S6640 与 S3776#368
github-actions[bot] merged 2 commits into
mainfrom
feature/gfx-591

Conversation

@AlianBlank

@AlianBlank AlianBlank commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Linear: GFX-591

Summary by CodeRabbit

  • 改进
    • 优化敏感词检测流程,提升文本扫描的稳定性与处理效率。
    • 改善单字符及多字符敏感词的识别与匹配表现。
    • 检测到匹配内容后可更及时地返回结果,减少不必要的扫描。

@linear-code

linear-code Bot commented Aug 6, 2026

Copy link
Copy Markdown

GFX-591

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

本次变更移除敏感词缓存初始化中的 unsafe 指针操作,并拆分检测扫描流程。多字符敏感词命中后立即返回。

Changes

敏感词检测重构

Layer / File(s) Summary
托管缓存初始化
GameFrameX.Utility/IllegalWordDetection.cs
RegisterBadWord 使用字符串索引访问字符。InitSkipBitArray 使用 foreach 初始化敏感词位置、长度、首尾字符缓存和跳过字符标记。
扫描流程拆分
GameFrameX.Utility/IllegalWordDetection.cs
DetectIllegalWords 委托 ScanFromPosition 执行扫描。AdvanceToNextStartChar 定位候选首字符。TryScanForward 执行多字符匹配,并在命中后立即返回。

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了移除 IllegalWordDetection 的 unsafe 指针和拆分 DetectIllegalWords 的主要变更,并指出了对应的 Sonar 问题。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/gfx-591

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@GameFrameX.Utility/IllegalWordDetection.cs`:
- Around line 534-580: Update ScanFromPosition so that when TryScanForward finds
a multi-character match and returnWhenFindFirst is false, it does not leave
aitorIdx at the match end or increment past the next overlapping start; preserve
the original scan start for the outer loop while continuing forward matching.
Keep the immediate return behavior unchanged when returnWhenFindFirst is true,
and apply the same cursor handling to the corresponding logic near the other
ScanFromPosition call site.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d97e0b3c-1015-44f0-a752-9988b0f356a1

📥 Commits

Reviewing files that changed from the base of the PR and between 1fc9055 and c930407.

📒 Files selected for processing (1)
  • GameFrameX.Utility/IllegalWordDetection.cs

Comment on lines +534 to +580
if (ScanFromPosition(text, textLength, ref aitorIdx, returnWhenFindFirst, findResult))
{
while (aitorIdx < textLength - 1 && (FastCheck[text[++aitorIdx]] & 0x01) == 0)
{
;
}
return true;
}
}

return findResult.Count > 0;
}

/// <summary>
/// 在主扫描循环的当前位置执行一次敏感词检测:推进游标到下一个候选首字符、记录单字符敏感词、向后扫描多字符敏感词。
/// 命中且需要首个即返回时返回 true;否则通过 ref 推进 aitorIdx 并返回 false。
/// </summary>
/// <remarks>
/// Performs one detection pass at the current cursor: advances to the next candidate start character,
/// records single-character bad words, then scans forward for multi-character bad words.
/// Returns true when a match is found and returnWhenFindFirst is set; otherwise advances aitorIdx via ref and returns false.
/// </remarks>
/// <param name="text">敏感词查询文本 / The text to check for sensitive words</param>
/// <param name="textLength">文本长度 / The text length</param>
/// <param name="aitorIdx">当前游标位置(引用),会被推进 / The current cursor (by ref), advanced by this call</param>
/// <param name="returnWhenFindFirst">是否找到第一个就返回 / Whether to return when the first match is found</param>
/// <param name="findResult">查找到的敏感词结果(键为起始位置,值为长度) / The found sensitive words (key is start position, value is length)</param>
/// <returns>是否找到敏感词并需立即返回 / Whether a match was found and the caller should return immediately</returns>
private static bool ScanFromPosition(string text, int textLength, ref int aitorIdx, bool returnWhenFindFirst, Dictionary<int, int> findResult)
{
aitorIdx = AdvanceToNextStartChar(text, textLength, aitorIdx);

//如果有只有一个词的敏感词,且当前的字符串的“非第一个词”满足这个敏感词,则先加入已检测到的敏感词列表
if (StartCache[text[aitorIdx]] != 0 && (FastLength[text[aitorIdx]] & 0x01) > 0)
//如果有只有一个词的敏感词,且当前的字符串的“非第一个词”满足这个敏感词,则先加入已检测到的敏感词列表
if (StartCache[text[aitorIdx]] != 0 && (FastLength[text[aitorIdx]] & 0x01) > 0)
{
//返回敏感词在text中的位置,以及敏感词的长度,供过滤功能用
findResult.Add(aitorIdx, 1);
if (returnWhenFindFirst)
{
//返回敏感词在text中的位置,以及敏感词的长度,供过滤功能用
findResult.Add(aitorIdx, 1);
if (returnWhenFindFirst)
{
return true;
}
return true;
}
}

//此时已经检测到一个敏感词的“首词”了,记录下第一个检测到的敏感词的位置
//从当前的位置检测到字符串末尾
if (TryScanForward(text, textLength, ref aitorIdx, findResult) && returnWhenFindFirst)
{
return true;
}

++aitorIdx;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

returnWhenFindFirstfalse 时,不要在首次多字符命中后跳过后续起始位置。

TryScanForward 在首次命中后把 aitorIdx 推进到匹配末尾。ScanFromPosition 随后再次递增该游标。此流程会跳过重叠敏感词。

例如,敏感词为 abbc,文本为 abc 时,当前代码只记录 abFilter 会产生 **c,而不会屏蔽 bc

仅当 returnWhenFindFirsttrue 时立即返回。否则,保持当前起始游标,并继续前向匹配和外层扫描。

建议修改
- if (TryScanForward(text, textLength, ref aitorIdx, findResult) && returnWhenFindFirst)
+ if (TryScanForward(text, textLength, aitorIdx, returnWhenFindFirst, findResult))
  {
      return true;
  }

- private static bool TryScanForward(string text, int textLength, ref int aitorIdx, Dictionary<int, int> findResult)
+ private static bool TryScanForward(string text, int textLength, int aitorIdx, bool returnWhenFindFirst, Dictionary<int, int> findResult)
  {
      // ...
      if (WordsSet.Contains(new string(_dectectedBuffer, 0, strIgorIdx)))
      {
          findResult[aitorIdx] = i + 1;
-         aitorIdx = subItoIdx;
-         return true;
+         if (returnWhenFindFirst)
+         {
+             return true;
+         }
      }
  }

Also applies to: 647-651

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@GameFrameX.Utility/IllegalWordDetection.cs` around lines 534 - 580, Update
ScanFromPosition so that when TryScanForward finds a multi-character match and
returnWhenFindFirst is false, it does not leave aitorIdx at the match end or
increment past the next overlapping start; preserve the original scan start for
the outer loop while continuing forward matching. Keep the immediate return
behavior unchanged when returnWhenFindFirst is true, and apply the same cursor
handling to the corresponding logic near the other ScanFromPosition call site.

@github-actions
github-actions Bot merged commit 8876aa6 into main Aug 7, 2026
1 of 3 checks passed
@github-actions
github-actions Bot deleted the feature/gfx-591 branch August 7, 2026 01:44
@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant