{"record":{"id":"a52df56e675b03fd","repo":"huiyadanli/RevokeMsgPatcher","slug":"error-a52df5","errorCode":null,"errorMessage":"不正确的通配符位置!","messagePattern":"不正确的通配符位置!","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"RevokeMsgPatcher/Matcher/FuzzyMatcher.cs","lineNumber":97,"sourceCode":"        /// <summary>\n        /// 获取头串\n        /// </summary>\n        /// <param name=\"whole\">完整查找串</param>\n        /// <returns></returns>\n        private static byte[] GetHead(byte[] whole)\n        {\n            int len = whole.Length;\n            for (int i = 0; i < whole.Length; i++)\n            {\n                if (whole[i] == wildcard)\n                {\n                    len = i;\n                    break;\n                }\n            }\n            if (len == 0)\n            {\n                throw new Exception(\"不正确的通配符位置!\");\n            }\n            return whole.Take(len).ToArray();\n        }\n\n        /// <summary>\n        /// 确认整个查找串是否匹配\n        /// </summary>\n        /// <param name=\"content\">被查找对象</param>\n        /// <param name=\"start\">头串匹配位置</param>\n        /// <param name=\"whole\">完整查找串</param>\n        /// <returns></returns>\n        public static bool IsEqual(byte[] content, int start, byte[] whole)\n        {\n            int i = 0;\n            for (i = 0; i < whole.Length; i++)\n            {\n                if (whole[i] == wildcard)\n                {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/huiyadanli/RevokeMsgPatcher/blob/89cbbb3f0cc896d5d092de0199a635c5c39944b6/RevokeMsgPatcher/Matcher/FuzzyMatcher.cs#L79-L115","documentation":"FuzzyMatcher.GetHead(pattern) extracts the concrete byte prefix before the first wildcard byte (0x3F, the ASCII '?'). Boyer-Moore anchoring needs at least one real leading byte; if the very first byte is a wildcard, len becomes 0 and it throws a plain Exception. A pattern must therefore not begin with a wildcard.","triggerScenarios":"A ReplacePattern.Search (or Replace) array whose first element equals 0x3F, i.e. a pattern authored as '?? XX YY' rather than 'XX ?? YY'. GetHead runs inside MatchAll/MatchNotReplaced on every search.","commonSituations":"Authoring patch signatures in patch.json with a leading wildcard; copying a signature from a disassembler that pads the start with ?? tokens.","solutions":["Rewrite the pattern so it starts with at least one concrete byte, not a wildcard (0x3F / '??').","If the signature genuinely has no fixed leading byte, find a nearby anchor and extend the pattern to include one concrete byte at the front.","Add an authoring-time check that rejects any Search/Replace array starting with 0x3F."],"exampleFix":"// before (throws)\nSearch  = ByteUtil.HexStringToByteArray(\"?? 8B 45 EC\");\n\n// after\nSearch  = ByteUtil.HexStringToByteArray(\"8B 45 EC ?? ?? 52\");","handlingStrategy":"validation","validationCode":"static bool HasValidHead(byte[] pattern) => pattern != null && pattern.Length > 0 && pattern[0] != FuzzyMatcher.wildcard;\n\nif (!HasValidHead(pattern.Search) || !HasValidHead(pattern.Replace))\n{\n    throw new InvalidOperationException(\"特征码不能以通配符(?? / 0x3F)开头\");\n}\nint[] idx = FuzzyMatcher.MatchAll(fileByteArray, pattern.Search);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never author a Search/Replace signature starting with 0x3F / '??'.","Add an authoring-time validator over patch.json that rejects leading-wildcard patterns.","When copying a signature from a disassembler, drop or relocate leading ?? tokens."],"tags":["matcher","wildcard","authoring"],"backgroundTag":null,"analyzedSha":"89cbbb3f0cc896d5d092de0199a635c5c39944b6","analyzedAt":"2026-08-13T10:37:37.073Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}