Skip to content

Commit a99ed67

Browse files
committed
Add ability to paste c-source files
The pasted C source files need to match up with what the verifier has or else we don't allow the contents to be overwritten.
1 parent ac796e6 commit a99ed67

File tree

3 files changed

+246
-3
lines changed

3 files changed

+246
-3
lines changed

src/App.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ function getVisibleLogLines(
6262

6363
function getVisibleCLines(
6464
verifierLogState: VerifierLogState,
65+
fileName: string = "",
66+
pastedLines: string[] = [],
6567
): [CSourceRow[], Map<string, number>] {
6668
const cLineIdToVisualIdx: Map<string, number> = new Map();
6769
const cLines: CSourceRow[] = [];
@@ -74,6 +76,24 @@ function getVisibleCLines(
7476
});
7577
++j;
7678

79+
if (file === fileName && pastedLines.length > 0) {
80+
pastedLines.forEach((lineText, i) => {
81+
const lineNum = i + 1;
82+
const sourceId = getCLineId(file, lineNum);
83+
cLines.push({
84+
type: "c_line",
85+
file,
86+
lineNum: i + 1,
87+
lineText,
88+
sourceId,
89+
ignore: false,
90+
});
91+
cLineIdToVisualIdx.set(sourceId, j);
92+
++j;
93+
});
94+
continue;
95+
}
96+
7797
let unknownStart = 0;
7898
for (let i = range[0]; i < range[1]; ++i) {
7999
const sourceId = getCLineId(file, i);
@@ -144,6 +164,7 @@ const ContentRaw = ({
144164
handleLogLinesOut,
145165
handleFullLogToggle,
146166
testListHeight,
167+
addPastedCSourceFile,
147168
}: {
148169
loadError: string | null;
149170
visualLogState: VisualLogState;
@@ -154,6 +175,7 @@ const ContentRaw = ({
154175
handleLogLinesOut: (event: React.MouseEvent<HTMLDivElement>) => void;
155176
handleFullLogToggle: () => void;
156177
testListHeight: number | undefined;
178+
addPastedCSourceFile: (fileName: string, pastedLines: string[]) => void;
157179
}) => {
158180
if (loadError) {
159181
return <div>{loadError}</div>;
@@ -167,6 +189,7 @@ const ContentRaw = ({
167189
handleLogLinesOut={handleLogLinesOut}
168190
handleFullLogToggle={handleFullLogToggle}
169191
testListHeight={testListHeight}
192+
addPastedCSourceFile={addPastedCSourceFile}
170193
/>
171194
);
172195
} else {
@@ -268,6 +291,24 @@ function App({ testListHeight }: { testListHeight?: number }) {
268291
setIsLoading(false);
269292
}, []);
270293

294+
const addPastedCSourceFile = useCallback(
295+
(fileName: string, pastedLines: string[]) => {
296+
setVisualLogState((prevState) => {
297+
const [cLines, cLineIdToVisualIdx] = getVisibleCLines(
298+
verifierLogState,
299+
fileName,
300+
pastedLines,
301+
);
302+
return {
303+
...prevState,
304+
cLines,
305+
cLineIdToVisualIdx,
306+
};
307+
});
308+
},
309+
[verifierLogState],
310+
);
311+
271312
const loadInputText = useCallback(
272313
(text: string) => {
273314
const rawLines = text.split("\n");
@@ -452,6 +493,7 @@ function App({ testListHeight }: { testListHeight?: number }) {
452493
handleLogLinesOut={handleLogLinesOut}
453494
handleFullLogToggle={handleFullLogToggle}
454495
testListHeight={testListHeight}
496+
addPastedCSourceFile={addPastedCSourceFile}
455497
/>
456498
<div id="hint">
457499
<SelectedLineHint

src/components.tsx

Lines changed: 139 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
BpfConditionalJmpInstruction,
1515
BpfTargetJmpInstruction,
1616
InstructionLine,
17+
getCLineId,
1718
} from "./parser";
1819
import {
1920
BpfMemSlotMap,
@@ -821,6 +822,98 @@ export function SelectedLineHint({
821822
);
822823
}
823824

825+
function CSourcePastePopup({
826+
verifierLogState,
827+
fileName,
828+
onHideCSourcePaste,
829+
addPastedCSourceFile,
830+
}: {
831+
verifierLogState: VerifierLogState;
832+
fileName: string;
833+
onHideCSourcePaste: () => void;
834+
addPastedCSourceFile: (fileName: string, pastedLines: string[]) => void;
835+
}) {
836+
const [pastedContent, setPastedContent] = useState("");
837+
const [mismatchError, setMismatcError] = useState(false);
838+
839+
const handleChange = useCallback(
840+
(event: ChangeEvent<HTMLTextAreaElement>) => {
841+
setMismatcError(false);
842+
const pastedText = event.target.value;
843+
setPastedContent(pastedText);
844+
const pastedLines: string[] = pastedText.split("\n");
845+
for (const [file] of verifierLogState.cSourceMap.fileRange) {
846+
if (file !== fileName) {
847+
continue;
848+
}
849+
pastedLines.some((lineText, i) => {
850+
const lineNum = i + 1;
851+
const sourceId = getCLineId(file, lineNum);
852+
const sourceLine =
853+
verifierLogState.cSourceMap.cSourceLines.get(sourceId);
854+
if (sourceLine && !sourceLine.ignore) {
855+
if (!lineText.includes(sourceLine.content)) {
856+
setMismatcError(true);
857+
return true;
858+
}
859+
}
860+
return false;
861+
});
862+
}
863+
},
864+
[],
865+
);
866+
867+
const handleConfirm = useCallback(() => {
868+
addPastedCSourceFile(fileName, pastedContent.split("\n"));
869+
onHideCSourcePaste();
870+
}, [pastedContent]);
871+
872+
const handleClear = useCallback(() => {
873+
setPastedContent("");
874+
setMismatcError(false);
875+
}, []);
876+
877+
const onContentClick = useCallback(
878+
(event: React.MouseEvent<HTMLDivElement>) => {
879+
event.stopPropagation();
880+
},
881+
[],
882+
);
883+
884+
return (
885+
<div onClick={onHideCSourcePaste} className="c-source-popup-overlay">
886+
<div onClick={onContentClick} className="c-source-popup-content">
887+
<h3>Paste contents of {fileName}</h3>
888+
<textarea
889+
className="c-source-textarea"
890+
value={pastedContent}
891+
onChange={handleChange}
892+
placeholder="Paste the entire file contents"
893+
/>
894+
{mismatchError && (
895+
<div className="c-source-popup-error">
896+
Pasted content does not match the verifier log.
897+
<br />
898+
Make sure the entire file contents are pasted and the line numbers
899+
match
900+
</div>
901+
)}
902+
<button
903+
className="c-source-button"
904+
onClick={handleConfirm}
905+
disabled={mismatchError || pastedContent === ""}
906+
>
907+
Apply
908+
</button>
909+
<button className="c-source-button" onClick={handleClear}>
910+
Clear
911+
</button>
912+
</div>
913+
</div>
914+
);
915+
}
916+
824917
function HideShowButton({
825918
isVisible,
826919
rightOpen,
@@ -1162,6 +1255,7 @@ type CSourceRowProps = {
11621255
cLines: CSourceRow[];
11631256
dependencyCLines: Set<string>;
11641257
selectedCLine: string;
1258+
onShowCSourcePaste: (fileName: string) => void;
11651259
};
11661260

11671261
function CSourceRowHeight(index: number, { cLines }: CSourceRowProps) {
@@ -1181,17 +1275,29 @@ const CSourceRowComponent = ({
11811275
cLines,
11821276
dependencyCLines,
11831277
selectedCLine,
1278+
onShowCSourcePaste,
11841279
}: RowComponentProps<CSourceRowProps>) => {
11851280
const item = cLines[index];
11861281

1282+
const onFilePasteClick = () => {
1283+
onShowCSourcePaste(item.file);
1284+
};
1285+
11871286
if (item.type == "file_name") {
11881287
const fileNameStyle = { ...style };
11891288
if (index === 0) {
11901289
fileNameStyle["borderTop"] = "0px";
11911290
}
11921291
return (
1193-
<div className="filename-header" style={fileNameStyle}>
1194-
{item.file}
1292+
<div
1293+
onClick={onFilePasteClick}
1294+
className="filename-header"
1295+
style={fileNameStyle}
1296+
>
1297+
{item.file} {"\u{1F4CB}"}
1298+
<div className="filename-tooltip">
1299+
Click to replace lines with actual source code
1300+
</div>
11951301
</div>
11961302
);
11971303
}
@@ -1241,6 +1347,7 @@ function CSourceLinesRaw({
12411347
handleFullLogToggle,
12421348
handleCLinesClick,
12431349
onCRowsRendered,
1350+
onShowCSourcePaste,
12441351
}: {
12451352
showFullLog: boolean;
12461353
selectedState: LogLineState;
@@ -1251,6 +1358,7 @@ function CSourceLinesRaw({
12511358
handleFullLogToggle: () => void;
12521359
handleCLinesClick: (event: React.MouseEvent<HTMLDivElement>) => void;
12531360
onCRowsRendered: (start: number, end: number) => void;
1361+
onShowCSourcePaste: (fileName: string) => void;
12541362
}) {
12551363
const buttonId = "csource-toggle";
12561364

@@ -1358,6 +1466,7 @@ function CSourceLinesRaw({
13581466
cLines: visualLogState.cLines,
13591467
dependencyCLines,
13601468
selectedCLine,
1469+
onShowCSourcePaste,
13611470
}}
13621471
/>
13631472
</div>
@@ -1375,6 +1484,7 @@ export function MainContent({
13751484
handleLogLinesOut,
13761485
handleFullLogToggle,
13771486
testListHeight,
1487+
addPastedCSourceFile,
13781488
}: {
13791489
visualLogState: VisualLogState;
13801490
selectedState: LogLineState;
@@ -1383,6 +1493,7 @@ export function MainContent({
13831493
handleLogLinesOut: (event: React.MouseEvent<HTMLDivElement>) => void;
13841494
handleFullLogToggle: () => void;
13851495
testListHeight: number | undefined;
1496+
addPastedCSourceFile: (fileName: string, pastedLines: string[]) => void;
13861497
}) {
13871498
const logListRef = useListRef(null);
13881499
const cListRef = useListRef(null);
@@ -1410,6 +1521,19 @@ export function MainContent({
14101521
visualLogEnd: number;
14111522
}>({ visualLogStart: 0, visualLogEnd: 0 });
14121523

1524+
const [cSourcePaste, setCSourcePaste] = useState<{
1525+
show: boolean;
1526+
fileName: string;
1527+
}>({ show: false, fileName: "" });
1528+
1529+
const onShowCSourcePaste = useCallback((fileName: string) => {
1530+
setCSourcePaste({ show: true, fileName });
1531+
}, []);
1532+
1533+
const onHideCSourcePaste = useCallback(() => {
1534+
setCSourcePaste({ show: false, fileName: "" });
1535+
}, []);
1536+
14131537
const onCRowsRendered = useCallback((start: number, end: number) => {
14141538
setVisualCIndexRange({ visualLogStart: start, visualLogEnd: end });
14151539
}, []);
@@ -1484,6 +1608,10 @@ export function MainContent({
14841608

14851609
useEffect(() => {
14861610
const handleKeyDown = (e: KeyboardEvent) => {
1611+
if (cSourcePaste.show) {
1612+
return;
1613+
}
1614+
14871615
let delta = 0;
14881616
let areCLinesInFocus = selectedState.cLine !== "";
14891617
let min = 0;
@@ -1931,6 +2059,7 @@ export function MainContent({
19312059
cListRef={cListRef}
19322060
onCRowsRendered={onCRowsRendered}
19332061
testListHeight={testListHeight}
2062+
onShowCSourcePaste={onShowCSourcePaste}
19342063
/>
19352064
<div
19362065
id="log-container"
@@ -1977,6 +2106,14 @@ export function MainContent({
19772106
handleStateCLineClick={handleStateCLineClick}
19782107
handleStateRowClick={handleStateRowClick}
19792108
/>
2109+
{cSourcePaste.show && (
2110+
<CSourcePastePopup
2111+
verifierLogState={verifierLogState}
2112+
onHideCSourcePaste={onHideCSourcePaste}
2113+
fileName={cSourcePaste.fileName}
2114+
addPastedCSourceFile={addPastedCSourceFile}
2115+
/>
2116+
)}
19802117
</div>
19812118
);
19822119
}

0 commit comments

Comments
 (0)