mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 09:23:52 -05:00
## Summary
Fixes unsafe type casting in assembly processing tools that was causing
`TypeError: text.split is not a function` runtime crashes.
## Root Cause Analysis
**COMPILER-EXPLORER-C2N** (57 occurrences) and **COMPILER-EXPLORER-AWW**
(184 occurrences):
The issue stemmed from tools making unsafe assumptions about
`compilationInfo.asm` type:
```typescript
// CompilationInfo.asm type (from types/compilation/compilation.interfaces.ts:168)
asm?: ParsedAsmResultLine[] | string; // "Temp hack until we get all code to agree on type of asm"
```
**The bug sequence:**
1. `base-compiler.ts:3120` converts string assembly to parsed format:
`result.asm = [{text: result.asm}]`
2. Tools unsafely cast back to string: `compilationInfo.asm as string`
3. `AsmParser.processBinaryAsm()` calls `splitLines(asmResult)`
4. If `asm` is actually `ParsedAsmResultLine[]`, `splitLines()` receives
an array
5. `text.split()` fails because arrays don't have `.split()` method
**Affected tools:** osaca-tool, x86to6502-tool, llvm-mca-tool
## Changes
### New Helper Functions in `utils.ts`:
1. **`extractTextLines(asm: string | any[]): string[]`**
- Safely extracts text lines from union types
- Throws descriptive errors for unexpected types (will surface in
Sentry)
2. **`normalizeAsmToString(asm: string | any[] | undefined): string`**
- Centralizes the common pattern of converting union type to string for
parser consumption
- Handles undefined gracefully
### Tool Fixes:
- **Removed unsafe casts**: `compilationInfo.asm as string` →
`normalizeAsmToString(compilationInfo.asm)`
- **Added null checks**: Explicit error handling for missing assembly
data
- **Type safety**: No more runtime type assumptions
## Impact
- Eliminates root cause of `text.split is not a function` errors (241+
occurrences combined)
- Maintains existing functionality - tools continue to work normally
- Better error messages when assembly data is missing
- Centralizes type handling logic for future maintainability
**Note:** The underlying architectural issue (union type "temp hack")
remains, but tools now handle it safely without crashes.
Fixes COMPILER-EXPLORER-C2N
Fixes COMPILER-EXPLORER-AWW
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Mats Jun Larsen <mats@jun.codes>
76 lines
3.2 KiB
TypeScript
76 lines
3.2 KiB
TypeScript
// Copyright (c) 2023, Compiler Explorer Team
|
|
// All rights reserved.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions are met:
|
|
//
|
|
// * Redistributions of source code must retain the above copyright notice,
|
|
// this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
// POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
// import {CompilationInfo} from '../../types/compilation/compilation.interfaces.js';
|
|
import {CompilationInfo} from '../../types/compilation/compilation.interfaces.js';
|
|
import {ToolResult} from '../../types/tool.interfaces.js';
|
|
import {AsmParser} from '../parsers/asm-parser.js';
|
|
import * as utils from '../utils.js';
|
|
|
|
import {BaseTool} from './base-tool.js';
|
|
|
|
export class x86to6502Tool extends BaseTool {
|
|
static get key() {
|
|
return 'x86to6502-tool';
|
|
}
|
|
|
|
override async runTool(compilationInfo: CompilationInfo, _inputFilepath?: string, args?: string[]) {
|
|
if (compilationInfo.filters.intel) {
|
|
return new Promise<ToolResult>(resolve => {
|
|
resolve(this.createErrorResponse('<need AT&T notation assembly>'));
|
|
});
|
|
}
|
|
|
|
if (compilationInfo.filters.binary) {
|
|
return new Promise<ToolResult>(resolve => {
|
|
resolve(this.createErrorResponse('<cannot run x86to6502 on binary>'));
|
|
});
|
|
}
|
|
|
|
if (!compilationInfo.asm) {
|
|
return this.createErrorResponse('<no assembly output available>');
|
|
}
|
|
|
|
const parser = new AsmParser();
|
|
const filters = Object.assign({}, compilationInfo.filters);
|
|
|
|
const asmString = utils.normalizeAsmToString(compilationInfo.asm);
|
|
const result = parser.process(asmString, filters);
|
|
|
|
const asm = result.asm
|
|
.map(obj => {
|
|
if (typeof obj.text !== 'string' || obj.text.trim() === '') {
|
|
return '';
|
|
}
|
|
if (/.*:/.test(obj.text)) {
|
|
return obj.text.replace(/^\s*/, '');
|
|
}
|
|
return obj.text.replace(/^\s*/, '\t');
|
|
})
|
|
.join('\n');
|
|
|
|
return super.runTool(compilationInfo, undefined, args, asm);
|
|
}
|
|
}
|