From cc088b2d9ec92bc34c9cb8a9c081734f9a890984 Mon Sep 17 00:00:00 2001 From: Michael Hohn Date: Wed, 19 Mar 2025 19:36:29 -0700 Subject: [PATCH] Add hybrid AST / CFG graph for illustration --- cfg.dot/cpp/ast-cfg-hybrid.dot | 266 +++++ cfg.dot/cpp/ast-cfg-hybrid.pdf | Bin 0 -> 55560 bytes cfg.dot/cpp/ast-cfg-hybrid.svg | 1671 ++++++++++++++++++++++++++++++++ readme-low-level.org | 79 +- 4 files changed, 1984 insertions(+), 32 deletions(-) create mode 100644 cfg.dot/cpp/ast-cfg-hybrid.dot create mode 100644 cfg.dot/cpp/ast-cfg-hybrid.pdf create mode 100644 cfg.dot/cpp/ast-cfg-hybrid.svg diff --git a/cfg.dot/cpp/ast-cfg-hybrid.dot b/cfg.dot/cpp/ast-cfg-hybrid.dot new file mode 100644 index 0000000..1f0f6b7 --- /dev/null +++ b/cfg.dot/cpp/ast-cfg-hybrid.dot @@ -0,0 +1,266 @@ +digraph { + compound=true; + + // Original AST nodes and edges + 0[label="[ExprStmt] ExprStmt"; ]; + 1[label="[FunctionCall] call to memcpy"; ]; + 2[label="[VariableAccess] input"; ]; + 3[label="[Literal] 0"; ]; + 4[label="[ArrayExpr] access to array"; ]; + 5[label="[ValueFieldAccess] ptr"; ]; + 6[label="[ValueFieldAccess] buf"; ]; + 7[label="[VariableAccess] input"; ]; + 8[label="[Literal] 1"; ]; + 9[label="[ArrayExpr] access to array"; ]; + 10[label="[ValueFieldAccess] ptr"; ]; + 11[label="[ValueFieldAccess] buf"; ]; + 12[label="[CStyleCast] (const void *)..."; ]; + 13[label="[VariableAccess] input"; ]; + 14[label="[Literal] 1"; ]; + 15[label="[ArrayExpr] access to array"; ]; + 16[label="[ValueFieldAccess] ptr"; ]; + 17[label="[ValueFieldAccess] size"; ]; + 18[label="[ExprStmt] ExprStmt"; ]; + 19[label="[FunctionCall] call to copy_mem_nested"; ]; + 20[label="[VariableAccess] input"; ]; + 21[label="[IfStmt] if (...) ... "; ]; + 22[label="[VariableAccess] input_types"; ]; + 23[label="[FunctionCall] call to DYN_INPUT_TYPE"; ]; + 24[label="[Literal] 1"; ]; + 25[label="[CStyleCast] (unsigned int)..."; ]; + 26[label="[Literal] 1"; ]; + 27[label="[CStyleCast] (unsigned int)..."; ]; + 28[label="[NEExpr] ... != ..."; ]; + 29[label="[BlockStmt] { ... }"; ]; + 30[label="[ExprStmt] ExprStmt"; ]; + 31[label="[FunctionCall] call to memcpy"; ]; + 32[label="[VariableAccess] input"; ]; + 33[label="[Literal] 0"; ]; + 34[label="[ArrayExpr] access to array"; ]; + 35[label="[ValueFieldAccess] ptr"; ]; + 36[label="[ValueFieldAccess] buf"; ]; + 37[label="[VariableAccess] input"; ]; + 38[label="[Literal] 1"; ]; + 39[label="[ArrayExpr] access to array"; ]; + 40[label="[ValueFieldAccess] ptr"; ]; + 41[label="[ValueFieldAccess] buf"; ]; + 42[label="[CStyleCast] (const void *)..."; ]; + 43[label="[VariableAccess] input"; ]; + 44[label="[Literal] 1"; ]; + 45[label="[ArrayExpr] access to array"; ]; + 46[label="[ValueFieldAccess] ptr"; ]; + 47[label="[ValueFieldAccess] size"; ]; + 48[label="[ExprStmt] ExprStmt"; ]; + 49[label="[FunctionCall] call to copy_mem_nested"; ]; + 50[label="[VariableAccess] input"; ]; + 51[label="[IfStmt] if (...) ... "; ]; + 52[label="[FunctionCall] call to DYN_INPUT_TYPE"; ]; + 53[label="[Literal] 1"; ]; + 54[label="[CStyleCast] (unsigned int)..."; ]; + 55[label="[Literal] 1"; ]; + 56[label="[CStyleCast] (unsigned int)..."; ]; + 57[label="[Literal] 100"; ]; + 58[label="[CStyleCast] (unsigned int)..."; ]; + 59[label="[EQExpr] ... == ..."; ]; + 60[label="[ExprStmt] ExprStmt"; ]; + 61[label="[FunctionCall] call to memcpy"; ]; + 62[label="[VariableAccess] input"; ]; + 63[label="[Literal] 0"; ]; + 64[label="[ArrayExpr] access to array"; ]; + 65[label="[ValueFieldAccess] ptr"; ]; + 66[label="[ValueFieldAccess] buf"; ]; + 67[label="[VariableAccess] input"; ]; + 68[label="[Literal] 1"; ]; + 69[label="[ArrayExpr] access to array"; ]; + 70[label="[ValueFieldAccess] ptr"; ]; + 71[label="[ValueFieldAccess] buf"; ]; + 72[label="[CStyleCast] (const void *)..."; ]; + 73[label="[VariableAccess] input"; ]; + 74[label="[Literal] 1"; ]; + 75[label="[ArrayExpr] access to array"; ]; + 76[label="[ValueFieldAccess] ptr"; ]; + 77[label="[ValueFieldAccess] size"; ]; + 78[label="[BlockStmt] { ... }"; ]; + 79[label="[IfStmt] if (...) ... "; ]; + 80[label="[VariableAccess] input_types"; ]; + 81[label="[FunctionCall] call to DYN_INPUT_TYPE"; ]; + 82[label="[Literal] 1"; ]; + 83[label="[CStyleCast] (unsigned int)..."; ]; + 84[label="[Literal] 1"; ]; + 85[label="[CStyleCast] (unsigned int)..."; ]; + 86[label="[NEExpr] ... != ..."; ]; + 87[label="[ReturnStmt] return ..."; ]; + 88[label="[Literal] 1"; ]; + 89[label="[BlockStmt] { ... }"; ]; + 90[label="[ExprStmt] ExprStmt"; ]; + 91[label="[FunctionCall] call to memcpy"; ]; + 92[label="[VariableAccess] input"; ]; + 93[label="[Literal] 0"; ]; + 94[label="[ArrayExpr] access to array"; ]; + 95[label="[ValueFieldAccess] ptr"; ]; + 96[label="[ValueFieldAccess] buf"; ]; + 97[label="[VariableAccess] input"; ]; + 98[label="[Literal] 1"; ]; + 99[label="[ArrayExpr] access to array"; ]; + 100[label="[ValueFieldAccess] ptr"; ]; + 101[label="[ValueFieldAccess] buf"; ]; + 102[label="[CStyleCast] (const void *)..."; ]; + 103[label="[VariableAccess] input"; ]; + 104[label="[Literal] 1"; ]; + 105[label="[ArrayExpr] access to array"; ]; + 106[label="[ValueFieldAccess] ptr"; ]; + 107[label="[ValueFieldAccess] size"; ]; + 108[label="[ExprStmt] ExprStmt"; ]; + 109[label="[FunctionCall] call to copy_mem_nested"; ]; + 110[label="[VariableAccess] input"; ]; + 111[label="[ReturnStmt] return ..."; ]; + 112[label="[Literal] 0"; ]; + 113[label="[BlockStmt] { ... }"; ]; + 114[label="[Parameter] unused"; ]; + 115[label="[Parameter] input"; ]; + 116[label="[Parameter] input_types"; ]; + 117[]; + 118[label="[TopLevelFunction] int copy_mem(unsigned int, dyn_input_t*, unsigned int)"; ]; + + // AST edges + 0 -> 1[label="getExpr()"; ]; + 1 -> 6[label="getArgument(0)"; ]; + 4 -> 2[label="getArrayBase()"; ]; + 5 -> 4[label="getQualifier()"; ]; + 6 -> 5[label="getQualifier()"; ]; + 9 -> 7[label="getArrayBase()"; ]; + 10 -> 9[label="getQualifier()"; ]; + 11 -> 10[label="getQualifier()"; ]; + 15 -> 13[label="getArrayBase()"; ]; + 16 -> 15[label="getQualifier()"; ]; + 17 -> 16[label="getQualifier()"; ]; + 18 -> 19[label="getExpr()"; ]; + 19 -> 20[label="getArgument(0)"; ]; + 21 -> 28[label="getCondition()"; ]; + 23 -> 24[label="getArgument(0)"; ]; + 28 -> 22[label="getLeftOperand()"; ]; + 30 -> 31[label="getExpr()"; ]; + 31 -> 36[label="getArgument(0)"; ]; + 34 -> 32[label="getArrayBase()"; ]; + 35 -> 34[label="getQualifier()"; ]; + 36 -> 35[label="getQualifier()"; ]; + 39 -> 37[label="getArrayBase()"; ]; + 40 -> 39[label="getQualifier()"; ]; + 41 -> 40[label="getQualifier()"; ]; + 45 -> 43[label="getArrayBase()"; ]; + 46 -> 45[label="getQualifier()"; ]; + 47 -> 46[label="getQualifier()"; ]; + 48 -> 49[label="getExpr()"; ]; + 49 -> 50[label="getArgument(0)"; ]; + 51 -> 59[label="getCondition()"; ]; + 52 -> 53[label="getArgument(0)"; ]; + 59 -> 52[label="getLeftOperand()"; ]; + 60 -> 61[label="getExpr()"; ]; + 61 -> 66[label="getArgument(0)"; ]; + 64 -> 62[label="getArrayBase()"; ]; + 65 -> 64[label="getQualifier()"; ]; + 66 -> 65[label="getQualifier()"; ]; + 69 -> 67[label="getArrayBase()"; ]; + 70 -> 69[label="getQualifier()"; ]; + 71 -> 70[label="getQualifier()"; ]; + 75 -> 73[label="getArrayBase()"; ]; + 76 -> 75[label="getQualifier()"; ]; + 77 -> 76[label="getQualifier()"; ]; + 78 -> 60[label="getStmt(0)"; ]; + 79 -> 86[label="getCondition()"; ]; + 81 -> 82[label="getArgument(0)"; ]; + 86 -> 80[label="getLeftOperand()"; ]; + 87 -> 88[label="getExpr()"; ]; + 89 -> 87[label="getStmt(0)"; ]; + 90 -> 91[label="getExpr()"; ]; + 91 -> 96[label="getArgument(0)"; ]; + 94 -> 92[label="getArrayBase()"; ]; + 95 -> 94[label="getQualifier()"; ]; + 96 -> 95[label="getQualifier()"; ]; + 99 -> 97[label="getArrayBase()"; ]; + 100 -> 99[label="getQualifier()"; ]; + 101 -> 100[label="getQualifier()"; ]; + 105 -> 103[label="getArrayBase()"; ]; + 106 -> 105[label="getQualifier()"; ]; + 107 -> 106[label="getQualifier()"; ]; + 108 -> 109[label="getExpr()"; ]; + 109 -> 110[label="getArgument(0)"; ]; + 111 -> 112[label="getExpr()"; ]; + 113 -> 0[label="getStmt(0)"; ]; + 118 -> 117[label=""; ]; + 117 -> 114[label="getParameter(0)"; ]; + 1 -> 11[label="getArgument(1)"; ]; + 4 -> 3[label="getArrayOffset()"; ]; + 9 -> 8[label="getArrayOffset()"; ]; + 15 -> 14[label="getArrayOffset()"; ]; + 21 -> 29[label="getThen()"; ]; + 23 -> 26[label="getArgument(1)"; ]; + 28 -> 23[label="getRightOperand()"; ]; + 31 -> 41[label="getArgument(1)"; ]; + 34 -> 33[label="getArrayOffset()"; ]; + 39 -> 38[label="getArrayOffset()"; ]; + 45 -> 44[label="getArrayOffset()"; ]; + 51 -> 78[label="getThen()"; ]; + 52 -> 55[label="getArgument(1)"; ]; + 59 -> 57[label="getRightOperand()"; ]; + 61 -> 71[label="getArgument(1)"; ]; + 64 -> 63[label="getArrayOffset()"; ]; + 69 -> 68[label="getArrayOffset()"; ]; + 75 -> 74[label="getArrayOffset()"; ]; + 79 -> 89[label="getThen()"; ]; + 81 -> 84[label="getArgument(1)"; ]; + 86 -> 81[label="getRightOperand()"; ]; + 91 -> 101[label="getArgument(1)"; ]; + 94 -> 93[label="getArrayOffset()"; ]; + 99 -> 98[label="getArrayOffset()"; ]; + 105 -> 104[label="getArrayOffset()"; ]; + 113 -> 18[label="getStmt(1)"; ]; + 118 -> 113[label="getEntryPoint()"; ]; + 117 -> 115[label="getParameter(1)"; ]; + 1 -> 17[label="getArgument(2)"; ]; + 23 -> 25[label="getArgument(0).getFullyConverted()"; ]; + 31 -> 47[label="getArgument(2)"; ]; + 52 -> 54[label="getArgument(0).getFullyConverted()"; ]; + 59 -> 58[label="getRightOperand().getFullyConverted()"; ]; + 61 -> 77[label="getArgument(2)"; ]; + 81 -> 83[label="getArgument(0).getFullyConverted()"; ]; + 91 -> 107[label="getArgument(2)"; ]; + 113 -> 21[label="getStmt(2)"; ]; + 117 -> 116[label="getParameter(2)"; ]; + 1 -> 12[label="getArgument(1).getFullyConverted()"; ]; + 23 -> 27[label="getArgument(1).getFullyConverted()"; ]; + 31 -> 42[label="getArgument(1).getFullyConverted()"; ]; + 52 -> 56[label="getArgument(1).getFullyConverted()"; ]; + 61 -> 72[label="getArgument(1).getFullyConverted()"; ]; + 81 -> 85[label="getArgument(1).getFullyConverted()"; ]; + 91 -> 102[label="getArgument(1).getFullyConverted()"; ]; + 113 -> 30[label="getStmt(3)"; ]; + 113 -> 48[label="getStmt(4)"; ]; + 113 -> 51[label="getStmt(5)"; ]; + 113 -> 79[label="getStmt(6)"; ]; + 113 -> 90[label="getStmt(7)"; ]; + 113 -> 108[label="getStmt(8)"; ]; + 113 -> 111[label="getStmt(9)"; ]; + + // First 17 CFG edges connected to AST nodes, numbered in CFG order + edge [color=blue, constraint=false, rankdir=none]; + + // Correspond to the first 17 CFG nodes/edges + 0 -> 2 [color=blue, label="1"]; // ExprStmt → input + 2 -> 3 [color=blue, label="2"]; // input → 0 + 3 -> 4 [color=blue, label="3"]; // 0 → access to array + 4 -> 5 [color=blue, label="4"]; // access to array → ptr + 5 -> 6 [color=blue, label="5"]; // ptr → buf + 6 -> 7 [color=blue, label="6"]; // buf → input + 7 -> 8 [color=blue, label="7"]; // input → 1 + 8 -> 9 [color=blue, label="8"]; // 1 → access to array + 9 -> 10 [color=blue, label="9"]; // access to array → ptr + 10 -> 11 [color=blue, label="10"]; // ptr → buf + 11 -> 12 [color=blue, label="11"]; // buf → input (second) + 12 -> 13 [color=blue, label="12"]; // input → 1 + 13 -> 14 [color=blue, label="13"]; // 1 → access to array + 14 -> 15 [color=blue, label="14"]; // access to array → ptr + 15 -> 16 [color=blue, label="15"]; // ptr → size + 16 -> 1 [color=blue, label="16"]; // size → call to memcpy + 1 -> 18 [color=blue, label="17"]; // call to memcpy → next ExprStmt +} diff --git a/cfg.dot/cpp/ast-cfg-hybrid.pdf b/cfg.dot/cpp/ast-cfg-hybrid.pdf new file mode 100644 index 0000000000000000000000000000000000000000..17bd35512b1a36546d3386d60c41dc0663f045c2 GIT binary patch literal 55560 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 KCZ=Vm&H8^QXu!e% literal 0 HcmV?d00001 diff --git a/cfg.dot/cpp/ast-cfg-hybrid.svg b/cfg.dot/cpp/ast-cfg-hybrid.svg new file mode 100644 index 0000000..2c147fa --- /dev/null +++ b/cfg.dot/cpp/ast-cfg-hybrid.svg @@ -0,0 +1,1671 @@ + + + + + + + + + +0 + +[ExprStmt] ExprStmt + + + +1 + +[FunctionCall] call to memcpy + + + +0->1 + + +getExpr() + + + +2 + +[VariableAccess] input + + + +0->2 + + +1 + + + +6 + +[ValueFieldAccess] buf + + + +1->6 + + +getArgument(0) + + + +11 + +[ValueFieldAccess] buf + + + +1->11 + + +getArgument(1) + + + +12 + +[CStyleCast] (const void *)... + + + +1->12 + + +getArgument(1).getFullyConverted() + + + +17 + +[ValueFieldAccess] size + + + +1->17 + + +getArgument(2) + + + +18 + +[ExprStmt] ExprStmt + + + +1->18 + + +17 + + + +3 + +[Literal] 0 + + + +2->3 + + +2 + + + +4 + +[ArrayExpr] access to array + + + +3->4 + + +3 + + + +4->2 + + +getArrayBase() + + + +4->3 + + +getArrayOffset() + + + +5 + +[ValueFieldAccess] ptr + + + +4->5 + + +4 + + + +5->4 + + +getQualifier() + + + +5->6 + + +5 + + + +6->5 + + +getQualifier() + + + +7 + +[VariableAccess] input + + + +6->7 + + +6 + + + +8 + +[Literal] 1 + + + +7->8 + + +7 + + + +9 + +[ArrayExpr] access to array + + + +8->9 + + +8 + + + +9->7 + + +getArrayBase() + + + +9->8 + + +getArrayOffset() + + + +10 + +[ValueFieldAccess] ptr + + + +9->10 + + +9 + + + +10->9 + + +getQualifier() + + + +10->11 + + +10 + + + +11->10 + + +getQualifier() + + + +11->12 + + +11 + + + +13 + +[VariableAccess] input + + + +12->13 + + +12 + + + +14 + +[Literal] 1 + + + +13->14 + + +13 + + + +15 + +[ArrayExpr] access to array + + + +14->15 + + +14 + + + +15->13 + + +getArrayBase() + + + +15->14 + + +getArrayOffset() + + + +16 + +[ValueFieldAccess] ptr + + + +15->16 + + +15 + + + +16->1 + + +16 + + + +16->15 + + +getQualifier() + + + +17->16 + + +getQualifier() + + + +19 + +[FunctionCall] call to copy_mem_nested + + + +18->19 + + +getExpr() + + + +20 + +[VariableAccess] input + + + +19->20 + + +getArgument(0) + + + +21 + +[IfStmt] if (...) ... + + + +28 + +[NEExpr] ... != ... + + + +21->28 + + +getCondition() + + + +29 + +[BlockStmt] { ... } + + + +21->29 + + +getThen() + + + +22 + +[VariableAccess] input_types + + + +23 + +[FunctionCall] call to DYN_INPUT_TYPE + + + +24 + +[Literal] 1 + + + +23->24 + + +getArgument(0) + + + +25 + +[CStyleCast] (unsigned int)... + + + +23->25 + + +getArgument(0).getFullyConverted() + + + +26 + +[Literal] 1 + + + +23->26 + + +getArgument(1) + + + +27 + +[CStyleCast] (unsigned int)... + + + +23->27 + + +getArgument(1).getFullyConverted() + + + +28->22 + + +getLeftOperand() + + + +28->23 + + +getRightOperand() + + + +30 + +[ExprStmt] ExprStmt + + + +31 + +[FunctionCall] call to memcpy + + + +30->31 + + +getExpr() + + + +36 + +[ValueFieldAccess] buf + + + +31->36 + + +getArgument(0) + + + +41 + +[ValueFieldAccess] buf + + + +31->41 + + +getArgument(1) + + + +42 + +[CStyleCast] (const void *)... + + + +31->42 + + +getArgument(1).getFullyConverted() + + + +47 + +[ValueFieldAccess] size + + + +31->47 + + +getArgument(2) + + + +32 + +[VariableAccess] input + + + +33 + +[Literal] 0 + + + +34 + +[ArrayExpr] access to array + + + +34->32 + + +getArrayBase() + + + +34->33 + + +getArrayOffset() + + + +35 + +[ValueFieldAccess] ptr + + + +35->34 + + +getQualifier() + + + +36->35 + + +getQualifier() + + + +37 + +[VariableAccess] input + + + +38 + +[Literal] 1 + + + +39 + +[ArrayExpr] access to array + + + +39->37 + + +getArrayBase() + + + +39->38 + + +getArrayOffset() + + + +40 + +[ValueFieldAccess] ptr + + + +40->39 + + +getQualifier() + + + +41->40 + + +getQualifier() + + + +43 + +[VariableAccess] input + + + +44 + +[Literal] 1 + + + +45 + +[ArrayExpr] access to array + + + +45->43 + + +getArrayBase() + + + +45->44 + + +getArrayOffset() + + + +46 + +[ValueFieldAccess] ptr + + + +46->45 + + +getQualifier() + + + +47->46 + + +getQualifier() + + + +48 + +[ExprStmt] ExprStmt + + + +49 + +[FunctionCall] call to copy_mem_nested + + + +48->49 + + +getExpr() + + + +50 + +[VariableAccess] input + + + +49->50 + + +getArgument(0) + + + +51 + +[IfStmt] if (...) ... + + + +59 + +[EQExpr] ... == ... + + + +51->59 + + +getCondition() + + + +78 + +[BlockStmt] { ... } + + + +51->78 + + +getThen() + + + +52 + +[FunctionCall] call to DYN_INPUT_TYPE + + + +53 + +[Literal] 1 + + + +52->53 + + +getArgument(0) + + + +54 + +[CStyleCast] (unsigned int)... + + + +52->54 + + +getArgument(0).getFullyConverted() + + + +55 + +[Literal] 1 + + + +52->55 + + +getArgument(1) + + + +56 + +[CStyleCast] (unsigned int)... + + + +52->56 + + +getArgument(1).getFullyConverted() + + + +57 + +[Literal] 100 + + + +58 + +[CStyleCast] (unsigned int)... + + + +59->52 + + +getLeftOperand() + + + +59->57 + + +getRightOperand() + + + +59->58 + + +getRightOperand().getFullyConverted() + + + +60 + +[ExprStmt] ExprStmt + + + +61 + +[FunctionCall] call to memcpy + + + +60->61 + + +getExpr() + + + +66 + +[ValueFieldAccess] buf + + + +61->66 + + +getArgument(0) + + + +71 + +[ValueFieldAccess] buf + + + +61->71 + + +getArgument(1) + + + +72 + +[CStyleCast] (const void *)... + + + +61->72 + + +getArgument(1).getFullyConverted() + + + +77 + +[ValueFieldAccess] size + + + +61->77 + + +getArgument(2) + + + +62 + +[VariableAccess] input + + + +63 + +[Literal] 0 + + + +64 + +[ArrayExpr] access to array + + + +64->62 + + +getArrayBase() + + + +64->63 + + +getArrayOffset() + + + +65 + +[ValueFieldAccess] ptr + + + +65->64 + + +getQualifier() + + + +66->65 + + +getQualifier() + + + +67 + +[VariableAccess] input + + + +68 + +[Literal] 1 + + + +69 + +[ArrayExpr] access to array + + + +69->67 + + +getArrayBase() + + + +69->68 + + +getArrayOffset() + + + +70 + +[ValueFieldAccess] ptr + + + +70->69 + + +getQualifier() + + + +71->70 + + +getQualifier() + + + +73 + +[VariableAccess] input + + + +74 + +[Literal] 1 + + + +75 + +[ArrayExpr] access to array + + + +75->73 + + +getArrayBase() + + + +75->74 + + +getArrayOffset() + + + +76 + +[ValueFieldAccess] ptr + + + +76->75 + + +getQualifier() + + + +77->76 + + +getQualifier() + + + +78->60 + + +getStmt(0) + + + +79 + +[IfStmt] if (...) ... + + + +86 + +[NEExpr] ... != ... + + + +79->86 + + +getCondition() + + + +89 + +[BlockStmt] { ... } + + + +79->89 + + +getThen() + + + +80 + +[VariableAccess] input_types + + + +81 + +[FunctionCall] call to DYN_INPUT_TYPE + + + +82 + +[Literal] 1 + + + +81->82 + + +getArgument(0) + + + +83 + +[CStyleCast] (unsigned int)... + + + +81->83 + + +getArgument(0).getFullyConverted() + + + +84 + +[Literal] 1 + + + +81->84 + + +getArgument(1) + + + +85 + +[CStyleCast] (unsigned int)... + + + +81->85 + + +getArgument(1).getFullyConverted() + + + +86->80 + + +getLeftOperand() + + + +86->81 + + +getRightOperand() + + + +87 + +[ReturnStmt] return ... + + + +88 + +[Literal] 1 + + + +87->88 + + +getExpr() + + + +89->87 + + +getStmt(0) + + + +90 + +[ExprStmt] ExprStmt + + + +91 + +[FunctionCall] call to memcpy + + + +90->91 + + +getExpr() + + + +96 + +[ValueFieldAccess] buf + + + +91->96 + + +getArgument(0) + + + +101 + +[ValueFieldAccess] buf + + + +91->101 + + +getArgument(1) + + + +102 + +[CStyleCast] (const void *)... + + + +91->102 + + +getArgument(1).getFullyConverted() + + + +107 + +[ValueFieldAccess] size + + + +91->107 + + +getArgument(2) + + + +92 + +[VariableAccess] input + + + +93 + +[Literal] 0 + + + +94 + +[ArrayExpr] access to array + + + +94->92 + + +getArrayBase() + + + +94->93 + + +getArrayOffset() + + + +95 + +[ValueFieldAccess] ptr + + + +95->94 + + +getQualifier() + + + +96->95 + + +getQualifier() + + + +97 + +[VariableAccess] input + + + +98 + +[Literal] 1 + + + +99 + +[ArrayExpr] access to array + + + +99->97 + + +getArrayBase() + + + +99->98 + + +getArrayOffset() + + + +100 + +[ValueFieldAccess] ptr + + + +100->99 + + +getQualifier() + + + +101->100 + + +getQualifier() + + + +103 + +[VariableAccess] input + + + +104 + +[Literal] 1 + + + +105 + +[ArrayExpr] access to array + + + +105->103 + + +getArrayBase() + + + +105->104 + + +getArrayOffset() + + + +106 + +[ValueFieldAccess] ptr + + + +106->105 + + +getQualifier() + + + +107->106 + + +getQualifier() + + + +108 + +[ExprStmt] ExprStmt + + + +109 + +[FunctionCall] call to copy_mem_nested + + + +108->109 + + +getExpr() + + + +110 + +[VariableAccess] input + + + +109->110 + + +getArgument(0) + + + +111 + +[ReturnStmt] return ... + + + +112 + +[Literal] 0 + + + +111->112 + + +getExpr() + + + +113 + +[BlockStmt] { ... } + + + +113->0 + + +getStmt(0) + + + +113->18 + + +getStmt(1) + + + +113->21 + + +getStmt(2) + + + +113->30 + + +getStmt(3) + + + +113->48 + + +getStmt(4) + + + +113->51 + + +getStmt(5) + + + +113->79 + + +getStmt(6) + + + +113->90 + + +getStmt(7) + + + +113->108 + + +getStmt(8) + + + +113->111 + + +getStmt(9) + + + +114 + +[Parameter] unused + + + +115 + +[Parameter] input + + + +116 + +[Parameter] input_types + + + +117 + +117 + + + +117->114 + + +getParameter(0) + + + +117->115 + + +getParameter(1) + + + +117->116 + + +getParameter(2) + + + +118 + +[TopLevelFunction] int copy_mem(unsigned int, dyn_input_t*, unsigned int) + + + +118->113 + + +getEntryPoint() + + + +118->117 + + +<params> + + + diff --git a/readme-low-level.org b/readme-low-level.org index 760aa06..feb641c 100644 --- a/readme-low-level.org +++ b/readme-low-level.org @@ -59,37 +59,6 @@ open cfg.dot/cpp/print-cfg.pdf #+END_SRC -* Original source code - #+BEGIN_SRC c++ - int copy_mem(unsigned int unused, dyn_input_t *input, - unsigned int input_types) { - memcpy(input[0].ptr.buf, input[1].ptr.buf, - input[1].ptr.size); // NON_COMPLIANT - type not checked - copy_mem_nested(input); // NON_COMPLIANT - type not checked - - if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) { - } - - memcpy(input[0].ptr.buf, input[1].ptr.buf, - input[1].ptr.size); // NON_COMPLIANT - guard doesn't control all paths - copy_mem_nested(input); // NON_COMPLIANT - guard doesn't control all paths - - if (DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM) == 100) { - memcpy(input[0].ptr.buf, input[1].ptr.buf, - input[1].ptr.size); // NON_COMPLIANT - useless type check - } - - if (input_types != DYN_INPUT_TYPE(DYN_INPUT_TYPE_MEM, DYN_INPUT_TYPE_MEM)) { - return 1; - } - - memcpy(input[0].ptr.buf, input[1].ptr.buf, - input[1].ptr.size); // COMPLIANT - type checked - copy_mem_nested(input); // COMPLIANT - type checked - - return 0; - } - #+END_SRC * AST The ast is inlined here. For better viewing, open the pdf ([[./ast.dot/cpp/print-ast.pdf]]) separately. @@ -102,4 +71,50 @@ #+ATTR_HTML: :class scrollable-svg [[./cfg.dot/cpp/print-cfg.svg]] - + +* GPTs + A gpt was used to add 17 of the CFG edges to the AST tree; more resulted in a + very confusing graph. The hybrid is in =cfg.dot/cpp/ast-cfg-hybrid.dot= + +* Render via dot + The hybrid is rendered via dot. The other renderers produced very spread + layouts. + #+BEGIN_SRC sh + # Convert dot to pdf + twopi -Tpdf < cfg.dot/cpp/ast-cfg-hybrid.dot > cfg.dot/cpp/ast-cfg-hybrid.pdf + circo -Tpdf < cfg.dot/cpp/ast-cfg-hybrid.dot > cfg.dot/cpp/ast-cfg-hybrid.pdf + dot -Tpdf < cfg.dot/cpp/ast-cfg-hybrid.dot > cfg.dot/cpp/ast-cfg-hybrid.pdf + dot -Tsvg < cfg.dot/cpp/ast-cfg-hybrid.dot > cfg.dot/cpp/ast-cfg-hybrid.svg + + # View the graph + open -a skim cfg.dot/cpp/ast-cfg-hybrid.pdf + #+END_SRC + +* AST-CFG HYBRID + The ast-cfg hybrid is inlined here. For better viewing, open the + pdf ([[./cfg.dot/cpp/ast-cfg-hybrid.pdf]]) separately. + #+ATTR_HTML: :width 100% + [[./cfg.dot/cpp/ast-cfg-hybrid.svg]] + +* Hybrid portion of source code + The part of the source code corresponding to the hybrid portion, with space for + adding edges: + #+BEGIN_SRC c++ + int copy_mem(unsigned int unused, dyn_input_t *input, + + + unsigned int input_types) { + + + memcpy(input[0].ptr.buf, input[1].ptr.buf, + + + input[1].ptr.size); + + + copy_mem_nested(input); + + ...; + } + #+END_SRC +