Skip to content

Commit 16c0ba9

Browse files
committed
Improve playground: better titles, error handling, and missed bug detection
- Clear titles: 'With Null Warnings' vs 'Without Null Warnings' - Show 'Missed N null safety bugs' when warnings suppressed - Better error messages with console reference - Display null bug count in stats - Bold Null-Safe Clang column in README comparison table
1 parent c92fd38 commit 16c0ba9

File tree

2 files changed

+26
-38
lines changed

2 files changed

+26
-38
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ Null pointer dereferences are just one category of memory safety bugs. Here's ho
3939
4040
### What Gets Fixed
4141
42-
| Safety Issue | Standard C | Null-Safe Clang (null checking) | Clang `-fbounds-safety` | Rust |
43-
|-------------|------------|-------------|-------------------------|------|
44-
| Null pointer dereferences | ❌ Unsafe | ✅ Fixed | ❌ Unsafe | ✅ Fixed |
42+
| Safety Issue | Standard C | **Null-Safe Clang** (null checking) | Clang `-fbounds-safety` | Rust |
43+
|-------------|------------|:-----------------------------------:|-------------------------|------|
44+
| Null pointer dereferences | ❌ Unsafe | **✅ Fixed** | ❌ Unsafe | ✅ Fixed |
4545
| Buffer overflows | ❌ Unsafe | ❌ Unsafe | ✅ Fixed | ✅ Fixed |
4646
| Use-after-free | ❌ Unsafe | ❌ Unsafe | ❌ Unsafe | ✅ Fixed |
4747
| Double-free | ❌ Unsafe | ❌ Unsafe | ❌ Unsafe | ✅ Fixed |

nullsafe-playground/index.html

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -553,12 +553,12 @@ <h1>Null-Safe Clang Playground</h1>
553553
</div>
554554
<div class="output-container">
555555
<div class="output-section">
556-
<div class="output-section-header">Null-Safe Clang (with null-safety warnings)</div>
556+
<div class="output-section-header">With Null Warnings</div>
557557
<div id="output-nullsafe" class="output-content"></div>
558558
</div>
559559
<div class="output-divider" id="outputDivider"></div>
560560
<div class="output-section">
561-
<div class="output-section-header">Null-Safe Clang (warnings suppressed with -Wno-nullability)</div>
561+
<div class="output-section-header">Without Null Warnings</div>
562562
<div id="output-mainline" class="output-content"></div>
563563
</div>
564564
</div>
@@ -931,10 +931,13 @@ <h1>Null-Safe Clang Playground</h1>
931931
const nullsafeCmd = `$ clang ${baseArgs}${nullsafeFlags.length ? ' ' + nullsafeFlags.join(' ') : ''} input.c`;
932932
const mainlineCmd = `$ clang ${baseArgs}${mainlineFlags.length ? ' ' + mainlineFlags.join(' ') : ''} input.c`;
933933

934-
// Update headers with compiler names
934+
// Update headers with clearer titles
935935
const headers = document.querySelectorAll('.output-section-header');
936-
headers[0].textContent = `Null-Safe Clang ${clangVersion} (with null-safety warnings)`;
937-
headers[1].textContent = `Null-Safe Clang ${clangVersion} (warnings suppressed with -Wno-nullability)`;
936+
headers[0].textContent = `With Null Warnings (v${clangVersion})`;
937+
headers[1].textContent = `Without Null Warnings (v${clangVersion})`;
938+
939+
// Count nullability warnings to detect missed bugs
940+
const nullWarningCount = (nullsafeResult.stderr.match(/\[-Wnullability\]/g) || []).length;
938941

939942
// Display null-safe results with command
940943
if (nullsafeResult.stdout || nullsafeResult.stderr) {
@@ -943,11 +946,16 @@ <h1>Null-Safe Clang Playground</h1>
943946
outputNullsafe.textContent = nullsafeCmd + '\n✓ No errors or warnings';
944947
}
945948

946-
// Display mainline results with command
949+
// Display mainline results with command and comparison
947950
if (mainlineResult.stdout || mainlineResult.stderr) {
948951
outputMainline.textContent = mainlineCmd + '\n' + mainlineResult.stderr + mainlineResult.stdout;
949952
} else {
950-
outputMainline.textContent = mainlineCmd + '\n✓ No errors or warnings';
953+
// No warnings suppressed, but check if null-safe had warnings
954+
if (nullWarningCount > 0) {
955+
outputMainline.textContent = mainlineCmd + '\n✓ No errors or warnings\n\n⚠️ Missed ' + nullWarningCount + ' null safety bug' + (nullWarningCount !== 1 ? 's' : '') + ' (see above)';
956+
} else {
957+
outputMainline.textContent = mainlineCmd + '\n✓ No errors or warnings';
958+
}
951959
}
952960

953961
// Calculate stats from null-safe results
@@ -957,15 +965,17 @@ <h1>Null-Safe Clang Playground</h1>
957965
let stats = [];
958966
if (errorCount > 0) stats.push(`${errorCount} error${errorCount !== 1 ? 's' : ''}`);
959967
if (warningCount > 0) stats.push(`${warningCount} warning${warningCount !== 1 ? 's' : ''}`);
968+
if (nullWarningCount > 0) stats.push(`(${nullWarningCount} null bug${nullWarningCount !== 1 ? 's' : ''})`);
960969
stats.push(`${duration}ms`);
961970

962971
outputStats.textContent = stats.join(' • ');
963972

964973
status.textContent = 'Ready to compile';
965974
status.className = 'status ready';
966975
} catch (error) {
967-
outputNullsafe.innerHTML = `<span class="error">Compilation failed: ${error.message}</span>`;
968-
outputMainline.innerHTML = `<span class="error">Compilation failed: ${error.message}</span>`;
976+
const errorMsg = error.message || String(error);
977+
outputNullsafe.innerHTML = `<span class="error">Compilation failed: ${errorMsg}\n\nCheck console for details.</span>`;
978+
outputMainline.innerHTML = `<span class="error">Compilation failed: ${errorMsg}\n\nCheck console for details.</span>`;
969979
status.textContent = 'Compilation error';
970980
status.className = 'status error';
971981
outputStats.textContent = '✗ Failed';
@@ -997,9 +1007,8 @@ <h1>Null-Safe Clang Playground</h1>
9971007
captureOutput = true;
9981008

9991009
try {
1000-
// Build command line arguments
1010+
// Build command line arguments (skip argv[0] for callMain)
10011011
const args = [
1002-
'clang', // argv[0]
10031012
'-fsyntax-only',
10041013
'--target=wasm32-unknown-emscripten',
10051014
...extraFlags,
@@ -1008,34 +1017,13 @@ <h1>Null-Safe Clang Playground</h1>
10081017

10091018
console.log('Compiling with args:', args);
10101019

1011-
// Allocate memory for argv array
1012-
const argc = args.length;
1013-
const argvPtrs = [];
1014-
1015-
// Allocate strings and collect pointers
1016-
for (let i = 0; i < argc; i++) {
1017-
const strPtr = Module.allocateUTF8(args[i]);
1018-
argvPtrs.push(strPtr);
1019-
}
1020-
1021-
// Allocate argv array
1022-
const argv = Module._malloc(argvPtrs.length * 4);
1023-
for (let i = 0; i < argvPtrs.length; i++) {
1024-
Module.HEAP32[(argv >> 2) + i] = argvPtrs[i];
1025-
}
1026-
1027-
// Call main directly
1028-
const exitCode = Module._main(argc, argv);
1020+
// Use callMain which handles argv properly
1021+
const exitCode = Module.callMain(args);
10291022
console.log('Clang exit code:', exitCode);
10301023

1031-
// Free allocated memory
1032-
for (let i = 0; i < argvPtrs.length; i++) {
1033-
Module._free(argvPtrs[i]);
1034-
}
1035-
Module._free(argv);
1036-
10371024
} catch (e) {
10381025
console.log('Clang execution error:', e);
1026+
throw e; // Re-throw to be caught by outer catch
10391027
}
10401028

10411029
// Disable capture

0 commit comments

Comments
 (0)