{"record":{"id":"ff71bcfd9032eef3","repo":"can1357/oh-my-pi","slug":"spelling-range-length-is-too-large","errorCode":null,"errorMessage":"spelling range length is too large","messagePattern":"spelling range length is too large","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"crates/pi-natives/src/spelling.rs","lineNumber":87,"sourceCode":"\t{\n\t\tlet (reply, result) = flume::bounded(1);\n\t\tSPELLING_THREAD\n\t\t\t.send(Box::new(move || {\n\t\t\t\tlet _ = reply.send(work());\n\t\t\t}))\n\t\t\t.map_err(|_| Error::new(Status::GenericFailure, \"native spelling thread stopped\"))?;\n\t\tresult\n\t\t\t.recv_async()\n\t\t\t.await\n\t\t\t.map_err(|_| Error::new(Status::GenericFailure, \"native spelling thread stopped\"))?\n\t}\n\n\tfn ns_range(start: u32, length: u32) -> Result<NSRange> {\n\t\tOk(NSRange {\n\t\t\tlocation: usize::try_from(start)\n\t\t\t\t.map_err(|_| Error::new(Status::InvalidArg, \"spelling range start is too large\"))?,\n\t\t\tlength:   usize::try_from(length)\n\t\t\t\t.map_err(|_| Error::new(Status::InvalidArg, \"spelling range length is too large\"))?,\n\t\t})\n\t}\n\n\tpub fn check(text: &str) -> Result<Vec<SpellingRange>> {\n\t\tlet checker = checker()?;\n\t\tlet text = NSString::from_str(text);\n\t\tlet full = NSRange { location: 0, length: text.length() };\n\t\t// `checkString:...` honors `automaticallyIdentifiesLanguages`, selecting\n\t\t// the dictionary per detected run; the legacy `checkSpellingOfString:`\n\t\t// used only the shared checker's single current language (issue #9334).\n\t\t// SAFETY: `options`/`orthography` are nil and `word_count` is null, all\n\t\t// documented as valid; the returned array is retained by objc2.\n\t\tlet results = unsafe {\n\t\t\tchecker.checkString_range_types_options_inSpellDocumentWithTag_orthography_wordCount(\n\t\t\t\t&text,\n\t\t\t\tfull,\n\t\t\t\tNSTextCheckingType::Spelling.bits(),\n\t\t\t\tNone,","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-natives/src/spelling.rs#L69-L105","documentation":"Same conversion boundary as the 'start is too large' variant, but for the range length: the u32 length is converted to usize for NSRange and the conversion failed. Like the start variant, this is only reachable where usize is narrower than u32 (32-bit targets); it protects the AppKit call from receiving a mangled NSRange.","triggerScenarios":"Calling a spelling API with a range length that cannot convert to usize — essentially only on 32-bit builds with length values at the top of the u32 range, or a bug producing an out-of-contract length internally.","commonSituations":"Extremely rare; would surface in 32-bit Electron/Node builds or with corrupted range metadata computed by the caller.","solutions":["Check the range length is a sane, non-negative value bounded by the text length","Clamp length to text.length - start before calling","Use a 64-bit build of the native module"],"exampleFix":"// before\nnative.checkSpelling(text, start, hugeLength);\n// after\nconst safeLen = Math.min(hugeLength >>> 0, text.length - start);\nnative.checkSpelling(text, start, safeLen);","handlingStrategy":"validation","validationCode":"if (!Number.isSafeInteger(length) || length < 0 || start + length > text.length) throw new RangeError('length out of range');","typeGuard":"const isValidLength = (l) => Number.isInteger(l) && l >= 0 && l <= 0xFFFFFFFF;","tryCatchPattern":"try {\n  return await native.checkSpelling(text, start, length);\n} catch (err) {\n  if (String(err?.message).includes('spelling range length is too large')) {\n    throw new RangeError(`spelling length ${length} rejected`);\n  } throw err;\n}","preventionTips":["Clamp length to text.length - start","Avoid computing lengths via unbounded arithmetic","Use 64-bit builds of the native module"],"tags":["native","macos","range","integer-overflow"],"backgroundTag":"range-offset-out-of-bounds","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}