From 4d28d58287e79265fb29e084351d0a0fe5924ddb Mon Sep 17 00:00:00 2001 From: Michael Hohn Date: Thu, 27 Mar 2025 21:43:19 -0700 Subject: [PATCH] Add dataflow graph, limited to first few lines of function --- ast.dot/cpp/print-dfg.dot | 342 +++++++ ast.dot/cpp/print-dfg.pdf | Bin 0 -> 41112 bytes ast.dot/cpp/print-dfg.svg | 2046 +++++++++++++++++++++++++++++++++++++ graphs/dfg.ql | 30 + readme-low-level.org | 33 +- 5 files changed, 2450 insertions(+), 1 deletion(-) create mode 100644 ast.dot/cpp/print-dfg.dot create mode 100644 ast.dot/cpp/print-dfg.pdf create mode 100644 ast.dot/cpp/print-dfg.svg create mode 100644 graphs/dfg.ql diff --git a/ast.dot/cpp/print-dfg.dot b/ast.dot/cpp/print-dfg.dot new file mode 100644 index 0000000..514ee69 --- /dev/null +++ b/ast.dot/cpp/print-dfg.dot @@ -0,0 +1,342 @@ +digraph { + compound=true; + 0[label="buf"; ]; + 1[label="buf"; ]; + 2[label="size"; ]; + 3[label="input"; ]; + 4[label="input"; ]; + 5[label="buf"; ]; + 6[label="input"; ]; + 7[label="input"; ]; + 8[label="input_types"; ]; + 9[label="buf"; ]; + 10[label="buf"; ]; + 11[label="size"; ]; + 12[label="input"; ]; + 13[label="input"; ]; + 14[label="buf"; ]; + 15[label="input"; ]; + 16[label="input"; ]; + 17[label="input"; ]; + 18[label="input"; ]; + 19[label="call to memcpy"; ]; + 20[label="call to memcpy"; ]; + 21[label="1"; ]; + 22[label="0"; ]; + 23[label="input"; ]; + 24[label="input"; ]; + 25[label="input"; ]; + 26[label="input_types"; ]; + 27[label="buf indirection"; ]; + 28[label="buf indirection"; ]; + 29[label="buf indirection"; ]; + 30[label="buf indirection"; ]; + 31[label="call to memcpy indirection"; ]; + 32[label="input indirection"; ]; + 33[label="access to array indirection"; ]; + 34[label="ptr indirection"; ]; + 35[label="input indirection"; ]; + 36[label="access to array indirection"; ]; + 37[label="ptr indirection"; ]; + 38[label="buf indirection"; ]; + 39[label="buf indirection"; ]; + 40[label="input indirection"; ]; + 41[label="access to array indirection"; ]; + 42[label="ptr indirection"; ]; + 43[label="input indirection"; ]; + 44[label="call to copy_mem_nested indirection"; ]; + 45[label="call to DYN_INPUT_TYPE indirection"; ]; + 46[label="buf indirection"; ]; + 47[label="buf indirection"; ]; + 48[label="buf indirection"; ]; + 49[label="buf indirection"; ]; + 50[label="call to memcpy indirection"; ]; + 51[label="input indirection"; ]; + 52[label="access to array indirection"; ]; + 53[label="ptr indirection"; ]; + 54[label="input indirection"; ]; + 55[label="access to array indirection"; ]; + 56[label="ptr indirection"; ]; + 57[label="buf indirection"; ]; + 58[label="buf indirection"; ]; + 59[label="input indirection"; ]; + 60[label="access to array indirection"; ]; + 61[label="ptr indirection"; ]; + 62[label="input indirection"; ]; + 63[label="call to copy_mem_nested indirection"; ]; + 64[label="input indirection"; ]; + 65[label="buf indirection"; ]; + 66[label="buf indirection"; ]; + 67[label="buf indirection"; ]; + 68[label="input indirection"; ]; + 69[label="buf indirection"; ]; + 70[label="buf indirection"; ]; + 71[label="buf indirection"; ]; + 72[label="input indirection"; ]; + 73[label="size indirection"; ]; + 74[label="input indirection"; ]; + 75[label="input indirection"; ]; + 76[label="buf indirection"; ]; + 77[label="buf indirection"; ]; + 78[label="buf indirection"; ]; + 79[label="input indirection"; ]; + 80[label="buf indirection"; ]; + 81[label="buf indirection"; ]; + 82[label="buf indirection"; ]; + 83[label="input indirection"; ]; + 84[label="size indirection"; ]; + 85[label="input indirection"; ]; + 86[label="unused indirection"; ]; + 87[label="input indirection"; ]; + 88[label="input indirection"; ]; + 89[label="input indirection"; ]; + 90[label="input_types indirection"; ]; + 91[label="copy_mem indirection"; ]; + 92[label="call to memcpy indirection"; ]; + 93[label="call to memcpy indirection"; ]; + 94[label="call to memcpy indirection"; ]; + 95[label="input indirection"; ]; + 96[label="access to array indirection"; ]; + 97[label="ptr indirection"; ]; + 98[label="buf indirection"; ]; + 99[label="buf indirection"; ]; + 100[label="buf indirection"; ]; + 101[label="input indirection"; ]; + 102[label="access to array indirection"; ]; + 103[label="ptr indirection"; ]; + 104[label="buf indirection"; ]; + 105[label="buf indirection"; ]; + 106[label="buf indirection"; ]; + 107[label="(const void *)... indirection"; ]; + 108[label="(const void *)... indirection"; ]; + 109[label="input indirection"; ]; + 110[label="access to array indirection"; ]; + 111[label="ptr indirection"; ]; + 112[label="size indirection"; ]; + 113[label="call to copy_mem_nested indirection"; ]; + 114[label="input indirection"; ]; + 115[label="call to DYN_INPUT_TYPE indirection"; ]; + 116[label="call to memcpy indirection"; ]; + 117[label="call to memcpy indirection"; ]; + 118[label="call to memcpy indirection"; ]; + 119[label="input indirection"; ]; + 120[label="access to array indirection"; ]; + 121[label="ptr indirection"; ]; + 122[label="buf indirection"; ]; + 123[label="buf indirection"; ]; + 124[label="buf indirection"; ]; + 125[label="input indirection"; ]; + 126[label="access to array indirection"; ]; + 127[label="ptr indirection"; ]; + 128[label="buf indirection"; ]; + 129[label="buf indirection"; ]; + 130[label="buf indirection"; ]; + 131[label="(const void *)... indirection"; ]; + 132[label="(const void *)... indirection"; ]; + 133[label="input indirection"; ]; + 134[label="access to array indirection"; ]; + 135[label="ptr indirection"; ]; + 136[label="size indirection"; ]; + 137[label="call to copy_mem_nested indirection"; ]; + 138[label="input indirection"; ]; + 139[label="input indirection"; ]; + 140[label="buf indirection"; ]; + 141[label="buf indirection"; ]; + 142[label="input indirection"; ]; + 143[label="buf indirection"; ]; + 144[label="buf indirection"; ]; + 145[label="input indirection"; ]; + 146[label="input indirection"; ]; + 147[label="input indirection"; ]; + 148[label="buf indirection"; ]; + 149[label="buf indirection"; ]; + 150[label="input indirection"; ]; + 151[label="buf indirection"; ]; + 152[label="buf indirection"; ]; + 153[label="input indirection"; ]; + 154[label="input indirection"; ]; + 155[label="unused indirection"; ]; + 156[label="input indirection"; ]; + 157[label="input indirection"; ]; + 158[label="input indirection"; ]; + 159[label="input_types indirection"; ]; + 160[label="copy_mem indirection"; ]; + 161[label="memcpy output argument"; ]; + 162[label="memcpy output argument"; ]; + 163[label="copy_mem_nested output argument"; ]; + 164[label="memcpy output argument"; ]; + 165[label="memcpy output argument"; ]; + 166[label="Phi"; ]; + 167[label="access to array indirection [post update]"; ]; + 168[label="access to array indirection [post update]"; ]; + 169[label="access to array indirection [post update]"; ]; + 170[label="access to array indirection [post update]"; ]; + 171[label="access to array indirection [post update]"; ]; + 172[label="access to array indirection [post update]"; ]; + 0 -> 19[]; + 3 -> 3[]; + 3 -> 4[]; + 4 -> 4[]; + 4 -> 6[]; + 5 -> 1[]; + 6 -> 6[]; + 6 -> 7[]; + 7 -> 7[]; + 7 -> 12[]; + 8 -> 8[]; + 9 -> 20[]; + 12 -> 12[]; + 12 -> 13[]; + 13 -> 13[]; + 13 -> 15[]; + 14 -> 10[]; + 15 -> 15[]; + 15 -> 16[]; + 16 -> 16[]; + 21 -> 166[]; + 22 -> 166[]; + 23 -> 17[]; + 23 -> 18[]; + 25 -> 87[]; + 26 -> 8[]; + 27 -> 93[]; + 28 -> 94[]; + 29 -> 93[]; + 29 -> 161[]; + 30 -> 162[]; + 32 -> 68[]; + 32 -> 96[]; + 33 -> 68[]; + 35 -> 72[]; + 35 -> 102[]; + 36 -> 72[]; + 38 -> 107[]; + 39 -> 108[]; + 40 -> 74[]; + 40 -> 110[]; + 41 -> 74[]; + 43 -> 75[]; + 46 -> 117[]; + 47 -> 118[]; + 48 -> 117[]; + 48 -> 164[]; + 49 -> 165[]; + 51 -> 79[]; + 51 -> 120[]; + 52 -> 79[]; + 54 -> 83[]; + 54 -> 126[]; + 55 -> 83[]; + 57 -> 131[]; + 58 -> 132[]; + 59 -> 85[]; + 59 -> 134[]; + 60 -> 85[]; + 64 -> 32[]; + 64 -> 139[]; + 65 -> 0[]; + 66 -> 140[]; + 67 -> 141[]; + 68 -> 35[]; + 68 -> 142[]; + 69 -> 5[]; + 70 -> 143[]; + 71 -> 144[]; + 72 -> 40[]; + 72 -> 145[]; + 73 -> 2[]; + 74 -> 43[]; + 74 -> 146[]; + 75 -> 51[]; + 75 -> 147[]; + 76 -> 9[]; + 77 -> 148[]; + 78 -> 149[]; + 79 -> 54[]; + 79 -> 150[]; + 80 -> 14[]; + 81 -> 151[]; + 82 -> 152[]; + 83 -> 59[]; + 83 -> 153[]; + 84 -> 11[]; + 85 -> 62[]; + 85 -> 154[]; + 87 -> 3[]; + 87 -> 24[]; + 88 -> 64[]; + 88 -> 157[]; + 92 -> 31[]; + 95 -> 64[]; + 96 -> 33[]; + 97 -> 34[]; + 98 -> 65[]; + 99 -> 66[]; + 100 -> 67[]; + 101 -> 68[]; + 102 -> 36[]; + 103 -> 37[]; + 104 -> 69[]; + 105 -> 70[]; + 106 -> 71[]; + 107 -> 29[]; + 108 -> 30[]; + 109 -> 72[]; + 110 -> 41[]; + 111 -> 42[]; + 112 -> 73[]; + 113 -> 44[]; + 114 -> 74[]; + 115 -> 45[]; + 116 -> 50[]; + 119 -> 75[]; + 120 -> 52[]; + 121 -> 53[]; + 122 -> 76[]; + 123 -> 77[]; + 124 -> 78[]; + 125 -> 79[]; + 126 -> 55[]; + 127 -> 56[]; + 128 -> 80[]; + 129 -> 81[]; + 130 -> 82[]; + 131 -> 48[]; + 132 -> 49[]; + 133 -> 83[]; + 134 -> 60[]; + 135 -> 61[]; + 136 -> 84[]; + 137 -> 63[]; + 138 -> 85[]; + 139 -> 32[]; + 140 -> 27[]; + 141 -> 28[]; + 142 -> 35[]; + 143 -> 38[]; + 144 -> 39[]; + 145 -> 40[]; + 146 -> 43[]; + 147 -> 51[]; + 148 -> 46[]; + 149 -> 47[]; + 150 -> 54[]; + 151 -> 57[]; + 152 -> 58[]; + 153 -> 59[]; + 154 -> 62[]; + 155 -> 86[]; + 156 -> 88[]; + 156 -> 89[]; + 158 -> 88[]; + 159 -> 90[]; + 160 -> 91[]; + 163 -> 75[]; + 166 -> 91[]; + 167 -> 68[]; + 168 -> 72[]; + 169 -> 74[]; + 170 -> 79[]; + 171 -> 83[]; + 172 -> 85[]; +} diff --git a/ast.dot/cpp/print-dfg.pdf b/ast.dot/cpp/print-dfg.pdf new file mode 100644 index 0000000000000000000000000000000000000000..716a87147365fd38141782289d6aacd4a78fbb0c GIT binary patch literal 41112 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 n*q!;g2>?isBgX&VrF(dqyL + + + + + + + + +0 + +buf + + + +19 + +call to memcpy + + + +0->19 + + + + + +1 + +buf + + + +2 + +size + + + +3 + +input + + + +3->3 + + + + + +4 + +input + + + +3->4 + + + + + +4->4 + + + + + +6 + +input + + + +4->6 + + + + + +5 + +buf + + + +5->1 + + + + + +6->6 + + + + + +7 + +input + + + +6->7 + + + + + +7->7 + + + + + +12 + +input + + + +7->12 + + + + + +8 + +input_types + + + +8->8 + + + + + +9 + +buf + + + +20 + +call to memcpy + + + +9->20 + + + + + +10 + +buf + + + +11 + +size + + + +12->12 + + + + + +13 + +input + + + +12->13 + + + + + +13->13 + + + + + +15 + +input + + + +13->15 + + + + + +14 + +buf + + + +14->10 + + + + + +15->15 + + + + + +16 + +input + + + +15->16 + + + + + +16->16 + + + + + +17 + +input + + + +18 + +input + + + +21 + +1 + + + +166 + +Phi + + + +21->166 + + + + + +22 + +0 + + + +22->166 + + + + + +23 + +input + + + +23->17 + + + + + +23->18 + + + + + +24 + +input + + + +25 + +input + + + +87 + +input indirection + + + +25->87 + + + + + +26 + +input_types + + + +26->8 + + + + + +27 + +buf indirection + + + +93 + +call to memcpy indirection + + + +27->93 + + + + + +28 + +buf indirection + + + +94 + +call to memcpy indirection + + + +28->94 + + + + + +29 + +buf indirection + + + +29->93 + + + + + +161 + +memcpy output argument + + + +29->161 + + + + + +30 + +buf indirection + + + +162 + +memcpy output argument + + + +30->162 + + + + + +31 + +call to memcpy indirection + + + +32 + +input indirection + + + +68 + +input indirection + + + +32->68 + + + + + +96 + +access to array indirection + + + +32->96 + + + + + +33 + +access to array indirection + + + +33->68 + + + + + +34 + +ptr indirection + + + +35 + +input indirection + + + +72 + +input indirection + + + +35->72 + + + + + +102 + +access to array indirection + + + +35->102 + + + + + +36 + +access to array indirection + + + +36->72 + + + + + +37 + +ptr indirection + + + +38 + +buf indirection + + + +107 + +(const void *)... indirection + + + +38->107 + + + + + +39 + +buf indirection + + + +108 + +(const void *)... indirection + + + +39->108 + + + + + +40 + +input indirection + + + +74 + +input indirection + + + +40->74 + + + + + +110 + +access to array indirection + + + +40->110 + + + + + +41 + +access to array indirection + + + +41->74 + + + + + +42 + +ptr indirection + + + +43 + +input indirection + + + +75 + +input indirection + + + +43->75 + + + + + +44 + +call to copy_mem_nested indirection + + + +45 + +call to DYN_INPUT_TYPE indirection + + + +46 + +buf indirection + + + +117 + +call to memcpy indirection + + + +46->117 + + + + + +47 + +buf indirection + + + +118 + +call to memcpy indirection + + + +47->118 + + + + + +48 + +buf indirection + + + +48->117 + + + + + +164 + +memcpy output argument + + + +48->164 + + + + + +49 + +buf indirection + + + +165 + +memcpy output argument + + + +49->165 + + + + + +50 + +call to memcpy indirection + + + +51 + +input indirection + + + +79 + +input indirection + + + +51->79 + + + + + +120 + +access to array indirection + + + +51->120 + + + + + +52 + +access to array indirection + + + +52->79 + + + + + +53 + +ptr indirection + + + +54 + +input indirection + + + +83 + +input indirection + + + +54->83 + + + + + +126 + +access to array indirection + + + +54->126 + + + + + +55 + +access to array indirection + + + +55->83 + + + + + +56 + +ptr indirection + + + +57 + +buf indirection + + + +131 + +(const void *)... indirection + + + +57->131 + + + + + +58 + +buf indirection + + + +132 + +(const void *)... indirection + + + +58->132 + + + + + +59 + +input indirection + + + +85 + +input indirection + + + +59->85 + + + + + +134 + +access to array indirection + + + +59->134 + + + + + +60 + +access to array indirection + + + +60->85 + + + + + +61 + +ptr indirection + + + +62 + +input indirection + + + +63 + +call to copy_mem_nested indirection + + + +64 + +input indirection + + + +64->32 + + + + + +139 + +input indirection + + + +64->139 + + + + + +65 + +buf indirection + + + +65->0 + + + + + +66 + +buf indirection + + + +140 + +buf indirection + + + +66->140 + + + + + +67 + +buf indirection + + + +141 + +buf indirection + + + +67->141 + + + + + +68->35 + + + + + +142 + +input indirection + + + +68->142 + + + + + +69 + +buf indirection + + + +69->5 + + + + + +70 + +buf indirection + + + +143 + +buf indirection + + + +70->143 + + + + + +71 + +buf indirection + + + +144 + +buf indirection + + + +71->144 + + + + + +72->40 + + + + + +145 + +input indirection + + + +72->145 + + + + + +73 + +size indirection + + + +73->2 + + + + + +74->43 + + + + + +146 + +input indirection + + + +74->146 + + + + + +75->51 + + + + + +147 + +input indirection + + + +75->147 + + + + + +76 + +buf indirection + + + +76->9 + + + + + +77 + +buf indirection + + + +148 + +buf indirection + + + +77->148 + + + + + +78 + +buf indirection + + + +149 + +buf indirection + + + +78->149 + + + + + +79->54 + + + + + +150 + +input indirection + + + +79->150 + + + + + +80 + +buf indirection + + + +80->14 + + + + + +81 + +buf indirection + + + +151 + +buf indirection + + + +81->151 + + + + + +82 + +buf indirection + + + +152 + +buf indirection + + + +82->152 + + + + + +83->59 + + + + + +153 + +input indirection + + + +83->153 + + + + + +84 + +size indirection + + + +84->11 + + + + + +85->62 + + + + + +154 + +input indirection + + + +85->154 + + + + + +86 + +unused indirection + + + +87->3 + + + + + +87->24 + + + + + +88 + +input indirection + + + +88->64 + + + + + +157 + +input indirection + + + +88->157 + + + + + +89 + +input indirection + + + +90 + +input_types indirection + + + +91 + +copy_mem indirection + + + +92 + +call to memcpy indirection + + + +92->31 + + + + + +95 + +input indirection + + + +95->64 + + + + + +96->33 + + + + + +97 + +ptr indirection + + + +97->34 + + + + + +98 + +buf indirection + + + +98->65 + + + + + +99 + +buf indirection + + + +99->66 + + + + + +100 + +buf indirection + + + +100->67 + + + + + +101 + +input indirection + + + +101->68 + + + + + +102->36 + + + + + +103 + +ptr indirection + + + +103->37 + + + + + +104 + +buf indirection + + + +104->69 + + + + + +105 + +buf indirection + + + +105->70 + + + + + +106 + +buf indirection + + + +106->71 + + + + + +107->29 + + + + + +108->30 + + + + + +109 + +input indirection + + + +109->72 + + + + + +110->41 + + + + + +111 + +ptr indirection + + + +111->42 + + + + + +112 + +size indirection + + + +112->73 + + + + + +113 + +call to copy_mem_nested indirection + + + +113->44 + + + + + +114 + +input indirection + + + +114->74 + + + + + +115 + +call to DYN_INPUT_TYPE indirection + + + +115->45 + + + + + +116 + +call to memcpy indirection + + + +116->50 + + + + + +119 + +input indirection + + + +119->75 + + + + + +120->52 + + + + + +121 + +ptr indirection + + + +121->53 + + + + + +122 + +buf indirection + + + +122->76 + + + + + +123 + +buf indirection + + + +123->77 + + + + + +124 + +buf indirection + + + +124->78 + + + + + +125 + +input indirection + + + +125->79 + + + + + +126->55 + + + + + +127 + +ptr indirection + + + +127->56 + + + + + +128 + +buf indirection + + + +128->80 + + + + + +129 + +buf indirection + + + +129->81 + + + + + +130 + +buf indirection + + + +130->82 + + + + + +131->48 + + + + + +132->49 + + + + + +133 + +input indirection + + + +133->83 + + + + + +134->60 + + + + + +135 + +ptr indirection + + + +135->61 + + + + + +136 + +size indirection + + + +136->84 + + + + + +137 + +call to copy_mem_nested indirection + + + +137->63 + + + + + +138 + +input indirection + + + +138->85 + + + + + +139->32 + + + + + +140->27 + + + + + +141->28 + + + + + +142->35 + + + + + +143->38 + + + + + +144->39 + + + + + +145->40 + + + + + +146->43 + + + + + +147->51 + + + + + +148->46 + + + + + +149->47 + + + + + +150->54 + + + + + +151->57 + + + + + +152->58 + + + + + +153->59 + + + + + +154->62 + + + + + +155 + +unused indirection + + + +155->86 + + + + + +156 + +input indirection + + + +156->88 + + + + + +156->89 + + + + + +158 + +input indirection + + + +158->88 + + + + + +159 + +input_types indirection + + + +159->90 + + + + + +160 + +copy_mem indirection + + + +160->91 + + + + + +163 + +copy_mem_nested output argument + + + +163->75 + + + + + +166->91 + + + + + +167 + +access to array indirection [post update] + + + +167->68 + + + + + +168 + +access to array indirection [post update] + + + +168->72 + + + + + +169 + +access to array indirection [post update] + + + +169->74 + + + + + +170 + +access to array indirection [post update] + + + +170->79 + + + + + +171 + +access to array indirection [post update] + + + +171->83 + + + + + +172 + +access to array indirection [post update] + + + +172->85 + + + + + diff --git a/graphs/dfg.ql b/graphs/dfg.ql new file mode 100644 index 0000000..70ddba4 --- /dev/null +++ b/graphs/dfg.ql @@ -0,0 +1,30 @@ +/** + * @name Print part of the DFG + * @description Outputs a subset of the data flow graph + * @id cpp/print-dfg + * @kind graph + */ + +// Just show the part for +// int copy_mem(unsigned int unused, dyn_input_t *input, +// unsigned int input_types) +import cpp +import semmle.code.cpp.dataflow.new.DataFlow + +query predicate nodes(DataFlow::Node n1, string key, string value) { + (edges(n1, _) or edges(_, n1)) and + ( + key = "color" and value = "black" + or + key = "line" and value = n1.getLocation().getStartLine().toString() + ) +} + +query predicate edges(DataFlow::Node n1, DataFlow::Node n2) { + exists(Function f1 | + f1.hasName("copy_mem") and + n1.getFunction() = f1 and + DataFlow::localFlowStep(n1, n2) and + n2.getLocation().getStartLine() < 46 + ) +} diff --git a/readme-low-level.org b/readme-low-level.org index 39278ab..eea9e4d 100644 --- a/readme-low-level.org +++ b/readme-low-level.org @@ -112,7 +112,6 @@ #+END_SRC - * Source Annotated with CFG Nodes The CFG entries #+BEGIN_SRC text @@ -150,3 +149,35 @@ } #+END_SRC +* DFG + The control flow graph and AST are narrowed to the function of interest, + #+BEGIN_SRC c++ + int copy_mem(unsigned int unused, dyn_input_t *input, + unsigned int input_types) {...} + + #+END_SRC + from [[./tests-common/test_part1.c]], so we do the same for the DFG. + + #+BEGIN_SRC sh + # Produce ast in dot format + codeql database analyze \ + --format=dot --output=ast.dot \ + -j8 -v --ram=16000 \ + --rerun \ + -- \ + cpp-dataflow-part1-database \ + graphs/dfg.ql + + # Convert dot to pdf + dot -Tpdf < ast.dot/cpp/print-dfg.dot > ast.dot/cpp/print-dfg.pdf + dot -Tsvg < ast.dot/cpp/print-dfg.dot > ast.dot/cpp/print-dfg.svg + + # View the graph + xdg-open ast.dot/cpp/print-dfg.pdf + + # This comes from + tests-common/test_part1.c + #+END_SRC + + +