From 44004760cb1253550e11fbbfd68fe7c73e8e9812 Mon Sep 17 00:00:00 2001 From: Yufeng He <40085740+he-yufeng@users.noreply.github.com> Date: Sat, 20 Jun 2026 15:26:14 +0800 Subject: [PATCH] fix(path_util): guard path_Mapping against IndexError on short relative targets path_Mapping accessed srcPath[1] (and srcPath[2] for "..") unconditionally in the relative-path branch. A mapping whose target is "." or ".." reduces srcPath to a one- or two-character string, so those accesses raised IndexError. The respond stage maps file component paths through path_Mapping, so a rule like "from:." would crash message handling. Read those characters defensively and fall through to the default normalization when they are absent. --- astrbot/core/utils/path_util.py | 5 +++-- tests/test_path_util.py | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 tests/test_path_util.py diff --git a/astrbot/core/utils/path_util.py b/astrbot/core/utils/path_util.py index 6fa2541fd3..8952435218 100644 --- a/astrbot/core/utils/path_util.py +++ b/astrbot/core/utils/path_util.py @@ -54,10 +54,11 @@ def path_Mapping(mappings, srcPath: str) -> str: has_replaced_processed = False if srcPath.startswith("."): # 相对路径处理。如果是相对路径,可能是Linux路径,也可能是Windows路径 - sign = srcPath[1] + # 映射目标可能短到只是 "." 或 "..",此时没有后续字符,按需取以免越界 + sign = srcPath[1] if len(srcPath) > 1 else "" # 处理两个点的情况 if sign == ".": - sign = srcPath[2] + sign = srcPath[2] if len(srcPath) > 2 else "" if sign == "/": srcPath = srcPath.replace("\\", "/") has_replaced_processed = True diff --git a/tests/test_path_util.py b/tests/test_path_util.py new file mode 100644 index 0000000000..d6762e9cce --- /dev/null +++ b/tests/test_path_util.py @@ -0,0 +1,19 @@ +from astrbot.core.utils.path_util import path_Mapping + + +def test_path_mapping_target_single_dot_does_not_crash(): + # A mapping whose target is "." reduces srcPath to "." (one character). + # The relative-path branch indexed srcPath[1] unconditionally and raised + # IndexError. path_Mapping is reachable from the respond stage, so a user + # configuring such a rule could crash message handling. + assert path_Mapping(["somepath:."], "somepath") == "." + + +def test_path_mapping_target_double_dot_does_not_crash(): + # ".." is two characters, so the inner srcPath[2] access also overran. + assert path_Mapping(["somepath:.."], "somepath") == ".." + + +def test_path_mapping_relative_target_still_normalized(): + # Regression: a normal relative target keeps its existing behaviour. + assert path_Mapping(["somepath:./sub"], "somepath") == "./sub"