Merge branch 'main' into rust-rusqlite

This commit is contained in:
Mathew Payne
2025-02-07 10:51:02 +00:00
committed by GitHub
1291 changed files with 93126 additions and 65569 deletions

View File

@@ -177,7 +177,7 @@ lib/codeql/rust/elements/Union.qll 92ffb1abc03889b9b71dae9491d4595e443c80b472474
lib/codeql/rust/elements/Use.qll e27d30ece0456a73732dfd867dfc5abdf48a50de56e7dafcab444b688610af72 7efe59c04dd2f10b4a25b8a17beb51362be0a93d73e5a9e1251cf133cf1227c3
lib/codeql/rust/elements/UseBoundGenericArg.qll f16903f8fff676d3700eaad5490804624391141472ecc3166ccb1f70c794c120 5efda98088d096b42f53ceccae78c05f15c6953525b514d849681cb2cf65b147
lib/codeql/rust/elements/UseBoundGenericArgs.qll 6d3b8bf8e59ef6d10d2f58c6d2eca61b113a524174f62d1f56b724c4179fda04 8fad6ed9e5bf159a2db01e7eb960cc55b940f7b92c4bb5c967120068e4fec80a
lib/codeql/rust/elements/UseTree.qll 16b6e42146dc4c2e9d8cc6bc143933d675d1a4c9a56b309f390f4bf5df99b25d 9f8dd7d621dd15f6f1ccec676b08da02773673cbb3a3570781c16167c6e08ef4
lib/codeql/rust/elements/UseTree.qll 69d96e5985ecdedc421d3d5da16b738ccdbb28ea01ca4d510b98f2a3409b28e5 0188c2744e89e19aa077c802e89faa87d62ca306adb71be8c3b23617f69a5982
lib/codeql/rust/elements/UseTreeList.qll 768c4ec25e8807bba65619f566b22fa5c0946c36e96c88cfdee04c2875b44554 6433c8d9acd4e346cadd5fef01d79dd35bb6245115bdceb5322c0511106030b0
lib/codeql/rust/elements/Variant.qll 328323ef59faf01dcf71e7d728fd10a60465a1bd24e1d3578289cdf6554e5b63 ba49c635790395d9df4398c3c0fec700c3c7761fcc6581623a45d381d23ac34d
lib/codeql/rust/elements/VariantList.qll 07adfe5750b2d5b50c8629f36feba24edd84f75698a80339d4cee20f4e95829d 7d322e60c84ea45f8c8b509226da7ae3c0125bcda42a98a94e3e6a9855cab79e
@@ -368,12 +368,10 @@ lib/codeql/rust/elements/internal/RecordExprFieldConstructor.qll 11620bc4e2dc7b3
lib/codeql/rust/elements/internal/RecordExprFieldListConstructor.qll 3a0d6ec872792c400d3a0a5ed1c5051b248a597a4b17ada1a078ea5d972b6721 52bae8222e7aa5bc89b73bec3fd1c3c1de0fe11bf30ccf5668454f63fbfc9b83
lib/codeql/rust/elements/internal/RecordExprFieldListImpl.qll 1210c23c0495f5d1a72409afc8c559f8da2b8c71340ff2944af9d1f684d0a856 fea96b053cad4135ab09b1c070a4c9f26507dd890a62c30772cf3e2358686640
lib/codeql/rust/elements/internal/RecordFieldConstructor.qll 9fc05f5101e48a45a028c479b35ec3d2f1a3cc33f0938667fcb813c5a4ab9526 98791dcf7f3209524f6132f9c26980e499cbcf94c1559e95c67544732245f05b
lib/codeql/rust/elements/internal/RecordFieldImpl.qll 2612dae3c95c9064420a3494872213f7fd7a3e1133243f4adea8a30808a209ae 143b75bb539a1bfea16e1c764a1f549522ef9c8d6d5de3fef377bbf67ba42075
lib/codeql/rust/elements/internal/RecordFieldListConstructor.qll 9f1d916f3784092dcbff7224451c8f4f0daf6f8293a466b0a30ec9b92cd41358 8aafe377714a134287362c4b96439c1c6baa5a31c2c36a544bd5f73e9213477a
lib/codeql/rust/elements/internal/RecordFieldListImpl.qll 1fa89578a1e27a7d6dd84c1cabbff08b38a3160ea0864c7be660984cf96fda1e 9fa6a775f0609f557548168424f02d068abb3978ba20a716c21619e904bd99f3
lib/codeql/rust/elements/internal/RecordPatConstructor.qll a5507e0db7cb297c74faa9d571e613799d7b3327584e4696d1d5c219d1ea84ba aa5c8042a88e99dca09a6ea7775bd6963825a3c2dd5d61f118dbbc57a336c4a1
lib/codeql/rust/elements/internal/RecordPatFieldConstructor.qll 6e1880ed05401b39c1e5e1a4eedb0a8a18c857aeb79c44c812cdc879eb3af1f4 1f7a5a2d4df22f7d7479fe348665d8a1411de47f8cc5b95b30ba4c3490ed8f61
lib/codeql/rust/elements/internal/RecordPatFieldImpl.qll 04bc31b857c8250096d9d1bf3fad1e556a28d83bb3f3b48a3f049048d1e6785f 5853105e55650d05a4b196f17b89baf12b898df0a010e4f88289ce01d16a0379
lib/codeql/rust/elements/internal/RecordPatFieldListConstructor.qll b8f0ef9b75ffe6be6ce7e601d528f0a1b871123c63e39cead3fd13b8bd4f54b7 166f07c708ab8b3de6bfaf193bac93081b2aacad046aa86de7441085dd20a8c5
lib/codeql/rust/elements/internal/RecordPatFieldListImpl.qll 2d1dd9910480eb65c59fcef2e1576ce639be85c35d90e4bce721ce22ec742ba3 1e788a2d7d00e9f96dbf7e93d3a18d5bfb4d7749194ff8e9810e9053fa88a94b
lib/codeql/rust/elements/internal/RefExprConstructor.qll 9ad08c0f3d980a56a2af8857cb84db589941d20ab3ae5c8ece004ccaccaaf950 4cac3ace31b7ed77a72e989fce9cdbae2247f03c28a3f0c50d67385d02c7f193
@@ -413,7 +411,6 @@ lib/codeql/rust/elements/internal/TryExprImpl.qll 00635685db339557cfb89fad0bfc13
lib/codeql/rust/elements/internal/TupleExprConstructor.qll 71c38786723225d3d90399b8a085b2b2664c62256654db9e1288fadd56745b9d 639ad70b49ebadc027127fbdc9de14e5180169a4285908233bc38ccac6f14110
lib/codeql/rust/elements/internal/TupleExprImpl.qll 23a0e4367fbcfcec3e2cf4a429f329a222b399c6729dd60f7ea42550273a6132 615f3b4897fdcbfddcf5c58e6edd64bf6e395923af89cc4e2a336099168bb6ad
lib/codeql/rust/elements/internal/TupleFieldConstructor.qll 89d3cf2540235044ed5a89706cfbdebc5cdf9180fd5b6d3376c79a1b2c0430c0 16861fe089aac8e42a5a90d81dd48d5015391d0a06c78ca02bd876d65378699f
lib/codeql/rust/elements/internal/TupleFieldImpl.qll f86d5df1598b9276bf2d6cb21a1daec8b27cef7a98db2b2ce91e4e0f9b3870ec b6db10ba5f6351bc1874daf47047ba74ada8b0011f355a44b6d529a1e9003657
lib/codeql/rust/elements/internal/TupleFieldListConstructor.qll 4335ba2061b6e4968db9ec05c0b4d3e6a564db89a2df69e036f317672a7900b1 0b8dded875dbf696cf588e8c21acc27332a2ff66ced7bfabdfc1ad621991f888
lib/codeql/rust/elements/internal/TupleFieldListImpl.qll ec17ddfe1d03210b7737f9c96b9d4003a91e504f3174e4b0eeba8a429eda2d6e ef6fb91c0d6b14b4d6bea6e516d5425d51d490956075ef314c72da59bfff5621
lib/codeql/rust/elements/internal/TuplePatConstructor.qll 2a5e83ad5b8713a732e610128aeddf14e9b344402d6cf30ff0b43aa39e838418 6d467f7141307523994f03ed7b8e8b1a5bcf860963c9934b90e54582ea38096a
@@ -443,7 +440,7 @@ lib/codeql/rust/elements/internal/UseBoundGenericArgsImpl.qll 43caeeb43b4b9480bd
lib/codeql/rust/elements/internal/UseConstructor.qll a4f790795e18abc29a50d6fbaa0db64cba781e3259a42cbf0468c24ac66b63e7 2fa288f073ac094a838c11f091def2c790b347b6a1b79407c11b10c73d6bff57
lib/codeql/rust/elements/internal/UseImpl.qll ba779517c3c928ab6e794360b6344829e84ec6da5e1de1b03b4eaf8bdae58ce9 0f4ead9eecb584eb9827502276ffe8cb1da0d2fa4b8f660d2afc26ac4e0fba86
lib/codeql/rust/elements/internal/UseTreeConstructor.qll 3e6e834100fcc7249f8a20f8bd9debe09b705fcf5a0e655537e71ac1c6f7956b cdbc84b8f1b009be1e4a7aaba7f5237823cea62c86b38f1794aad97e3dfcf64b
lib/codeql/rust/elements/internal/UseTreeImpl.qll 25e286538c048cc7ee07f4b5a8b77bc8b5a215fb206f4ab20163bd81dec0b90f fe44969d441c0c34bea1b0c25cdf35f25ea667c6e2da9ea067d230f484492715
lib/codeql/rust/elements/internal/UseTreeImpl.qll d478495a62e466fa4f443ffcf0d5235a7278fa9e8565267e73bb78210b7d54a1 76b71392b12f1bd7e66dd9e2902f48a1c27dce01fadad3a23e5a680d64fa0d49
lib/codeql/rust/elements/internal/UseTreeListConstructor.qll 973577da5d7b58eb245f108bd1ae2fecc5645f2795421dedf7687b067a233003 f41e5e3ffcb2a387e5c37f56c0b271e8dc20428b6ff4c63e1ee42fcfa4e67d0a
lib/codeql/rust/elements/internal/UseTreeListImpl.qll 6cac5242f1219df0fe9b3c139db8cc075a2fde618614ca56de2c856130a8ebaa d2ec917055a45f4d07d4ea6dff14298925ae323b165a5bcb6e906f7aad463f82
lib/codeql/rust/elements/internal/VariantConstructor.qll 0297d4a9a9b32448d6d6063d308c8d0e7a067d028b9ec97de10a1d659ee2cfdd 6a4bee28b340e97d06b262120fd39ab21717233a5bcc142ba542cb1b456eb952
@@ -579,10 +576,10 @@ lib/codeql/rust/elements/internal/generated/ParamList.qll c808c9d84dd7800573832b
lib/codeql/rust/elements/internal/generated/ParenExpr.qll bc0731505bfe88516205ec360582a4222d2681d11342c93e15258590ddee82f2 d4bd6e0c80cf1d63746c88d4bcb3a01d4c75732e5da09e3ebd9437ced227fb60
lib/codeql/rust/elements/internal/generated/ParenPat.qll 4f168ef5d5bb87a903251cc31b2e44a759b099ec69c90af31783fbb15778c940 0e34f94a45a13396fd57d94c245dc64d1adde2ab0e22b56946f7e94c04e297fc
lib/codeql/rust/elements/internal/generated/ParenTypeRepr.qll 40ab5c592e7699c621787793743e33988de71ff42ca27599f5ab3ddb70e3f7d8 12c0a6eed2202ee3e892f61da3b3ce77ac3190854cdf3097e8d2be98aa3cb91d
lib/codeql/rust/elements/internal/generated/ParentChild.qll 738612c1ec404fe8c090e0d234bdac4ce207bd0d4cad699a2981e6b6cb8947a9 df002e5540bfe5de4e6849879f334b09c2ffb4893ff8364146c6c505f4b2d090
lib/codeql/rust/elements/internal/generated/ParentChild.qll a180b0d0c8c33503dc4c013c3f568eaa628d24204bfc36a7484c56a701a79f95 df002e5540bfe5de4e6849879f334b09c2ffb4893ff8364146c6c505f4b2d090
lib/codeql/rust/elements/internal/generated/ParenthesizedArgList.qll c5fa328ea60d3a3333d7c7bb3480969c1873166c7ac8ebb9d0afad7a8099d1a8 2dbbb6200d96f7db7dea4a55bdeab8d67b14d39a43e0bd54ada019f7e466f163
lib/codeql/rust/elements/internal/generated/Pat.qll 3605ac062be2f294ee73336e9669027b8b655f4ad55660e1eab35266275154ee 7f9400db2884d336dd1d21df2a8093759c2a110be9bf6482ce8e80ae0fd74ed4
lib/codeql/rust/elements/internal/generated/Path.qll bf6a86e7fcb7164624cc070dcce86d2bda50a2516b95115b87d0ebb5596e50a1 fd7a9ad4034cdebe8dfe495619c46f464630d38195313072e0bd904061b0fb00
lib/codeql/rust/elements/internal/generated/Path.qll 8e47e91aff3f8c60f1ee8cb3887b8e4936c38e4665d052f2c92a939a969aac29 2c28beb89cabd7c7c91a5bc65c874f414cb96bbefde37b25811b61089a8a0053
lib/codeql/rust/elements/internal/generated/PathAstNode.qll e6d4d5bffd3c623baaaee46bc183eb31ce88795535f164f6a9b9b4d98bbd6101 168db515404933479ba6b150c72e012d28592cbc32366aefcb1bf9599dbcd183
lib/codeql/rust/elements/internal/generated/PathExpr.qll 34ebad4d062ce8b7e517f2ab09d52745fb8455203f4a936df7284ad296638387 ba66781cdbdeb89c27a4bfb2be0f27f85fb34978d699b4e343446fb0d7ad2aa6
lib/codeql/rust/elements/internal/generated/PathExprBase.qll d8218e201b8557fa6d9ca2c30b764e5ad9a04a2e4fb695cc7219bbd7636a6ac2 4ef178426d7095a156f4f8c459b4d16f63abc64336cb50a6cf883a5f7ee09113
@@ -594,7 +591,7 @@ lib/codeql/rust/elements/internal/generated/PtrTypeRepr.qll 51d1e9e683fc79dddbff
lib/codeql/rust/elements/internal/generated/PureSynthConstructors.qll e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f e5b8e69519012bbaae29dcb82d53f7f7ecce368c0358ec27ef6180b228a0057f
lib/codeql/rust/elements/internal/generated/RangeExpr.qll 23cca03bf43535f33b22a38894f70d669787be4e4f5b8fe5c8f7b964d30e9027 18624cef6c6b679eeace2a98737e472432e0ead354cca02192b4d45330f047c9
lib/codeql/rust/elements/internal/generated/RangePat.qll 80826a6a6868a803aa2372e31c52a03e1811a3f1f2abdb469f91ca0bfdd9ecb6 34ee1e208c1690cba505dff2c588837c0cd91e185e2a87d1fe673191962276a9
lib/codeql/rust/elements/internal/generated/Raw.qll c75c7811d041897c2d6aae1e0e55b46af6182565e1d0dd624062c5ca499e9325 79e6ded808f14dd622076b75d8e4985c7b90f2d5e964d0750519b510463b47ba
lib/codeql/rust/elements/internal/generated/Raw.qll 5f812a8c841d33127bccca5d3939ad63d0a084cc4df22f43eb84df04f874b2e1 917369eb790c67405d4c32737204bcf919c5c52c5581a48f79b0d35909bb1160
lib/codeql/rust/elements/internal/generated/RecordExpr.qll 2131b2cb336caa76170082e69776011bf02576bbfdd34ba68ca84af24209250a 39a2e3ec32352b594c43cc1295e0e8b3f9808173322d3d73cb7d48ef969d5565
lib/codeql/rust/elements/internal/generated/RecordExprField.qll 7e9f8663d3b74ebbc9603b10c9912f082febba6bd73d344b100bbd3edf837802 fbe6b578e7fd5d5a6f21bbb8c388957ab7210a6a249ec71510a50fb35b319ea1
lib/codeql/rust/elements/internal/generated/RecordExprFieldList.qll 179a97211fe7aa6265085d4d54115cdbc0e1cd7c9b2135591e8f36d6432f13d3 dd44bbbc1e83a1ed3a587afb729d7debf7aeb7b63245de181726af13090e50c0
@@ -646,7 +643,7 @@ lib/codeql/rust/elements/internal/generated/Union.qll 06a602aa7c7097e72fff6ea33d
lib/codeql/rust/elements/internal/generated/Use.qll d42ccf3516a9f79ae8766f93ad5f09d3cdcd7b96844d4c9de64189b56018a7b4 70a9553a8f71f6cbfdd0f59a4b42292d13177613ceb0542436436e0ac2e1f8ee
lib/codeql/rust/elements/internal/generated/UseBoundGenericArg.qll 69162794e871291545ea04f61259b2d000671a96f7ca129f7dd9ed6e984067c4 31de9ebc0634b38e2347e0608b4ea888892f1f2732a2892464078cd8a07b4ee8
lib/codeql/rust/elements/internal/generated/UseBoundGenericArgs.qll 05dca015d922935887856f3a0d577dbcf5b8f82bc384bdc9c8c2d0106419716d fcee14ed4f7a639b1ba721bd390fc0cdbfdc7c759e3092aa462d466fe390de45
lib/codeql/rust/elements/internal/generated/UseTree.qll b39cbc96e473802372726d580febbfa7d73668ba476095aa4a61fae914865913 40ce6515b7df068fa8c0a7e5ae8984f50b71f6f96d625d631b28d525e3e868b7
lib/codeql/rust/elements/internal/generated/UseTree.qll 15b84e3a194959aef793cd0c16b3d2d21ee5822e2d26186b5d73f922325c2827 49c409a7b82c1099436fbe3bd041d35dcd23169d58d31fbd718f6deb96fb7318
lib/codeql/rust/elements/internal/generated/UseTreeList.qll 829441cf309f008a6a9d2e784aa414ab4c11880a658f8ee71aa4df385cd2b6a8 ced82df94fea7a191f414f7e6496d13791d2f535046844b6f712a390663ac3d0
lib/codeql/rust/elements/internal/generated/Variant.qll e40dbb23e07c5b70adc577efdf7a064e773207f216cad8fe8905882b1da9f4a9 13f7be36d043afcfc156d2c01bb828de882df69aa732f284aa76c5f00b063544
lib/codeql/rust/elements/internal/generated/VariantList.qll 4eb923ca341033c256ca9b8a8a5b4e14c7eac9d015be187fd97eeb25dfb1e18e e7865e975c35db49cd72cb8f9864797d3cfed16c3a675b5032b867ced2bbb405
@@ -1189,7 +1186,7 @@ test/extractor-tests/generated/Use/Use_getExtendedCanonicalPath.ql ccfde95c861cf
test/extractor-tests/generated/Use/Use_getUseTree.ql 1dfe6bb40b29fbf823d67fecfc36ba928b43f17c38227b8eedf19fa252edf3af aacdcc4cf418ef1eec267287d2af905fe73f5bcfb080ef5373d08da31c608720
test/extractor-tests/generated/Use/Use_getVisibility.ql 587f80acdd780042c48aeb347004be5e9fd9df063d263e6e4f2b660c48c53a8f 0c2c04f95838bca93dfe93fa208e1df7677797efc62b4e8052a4f9c5d20831dd
test/extractor-tests/generated/UseBoundGenericArgs/MISSING_SOURCE.txt b6cf5771fdbbe981aeb3f443ec7a40517b6e99ffc9817fd8872c2e344240dae1 b6cf5771fdbbe981aeb3f443ec7a40517b6e99ffc9817fd8872c2e344240dae1
test/extractor-tests/generated/UseTree/UseTree.ql cb9f63051ae08cf8557b86b69b02cefe1732fc1e2daec34bcb891e271829cd86 eb46496aab9252b21eb0ccdd75792a97264885259c23d7e17e3013d943783947
test/extractor-tests/generated/UseTree/UseTree.ql e305edd22df9e018a58f932774447354b7fcf0ba871b52b35f0ee9cd4f6dacdf 766a84116aa8ff3d90343c6730bcb161ff1d447bdb049cd21d6b2bbf3cb9032c
test/extractor-tests/generated/UseTree/UseTree_getPath.ql 80384a99674bdda85315a36681cb22ad2ad094005a5543b63d930fc7e030dd5b 2cd92b5de8b4214527f8a58d641430f6804d9bd40927e1da0c7efda2f86f6544
test/extractor-tests/generated/UseTree/UseTree_getRename.ql ec3917501f3c89ac4974fab3f812d00b159ae6f2402dd20e5b4b3f8e8426391d db9ed981ce5f822aee349e5841d3126af7878d90e64140756ab4519552defe72
test/extractor-tests/generated/UseTree/UseTree_getUseTreeList.ql c265a88347e813840969ae934dfd2904bc06f502de77709bc0b1c7255e46382a 52a239c8ea5fd8fbfbd606559d70ecadc769887437a9bcab6fb3e774208ad868

3
rust/ql/.gitattributes generated vendored
View File

@@ -370,12 +370,10 @@
/lib/codeql/rust/elements/internal/RecordExprFieldListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordExprFieldListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordFieldConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordFieldImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordFieldListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordFieldListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordPatConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordPatFieldConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordPatFieldImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordPatFieldListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/RecordPatFieldListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/RefExprConstructor.qll linguist-generated
@@ -415,7 +413,6 @@
/lib/codeql/rust/elements/internal/TupleExprConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/TupleExprImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/TupleFieldConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/TupleFieldImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/TupleFieldListConstructor.qll linguist-generated
/lib/codeql/rust/elements/internal/TupleFieldListImpl.qll linguist-generated
/lib/codeql/rust/elements/internal/TuplePatConstructor.qll linguist-generated

View File

@@ -14,11 +14,11 @@
| Macro calls - resolved | 2 |
| Macro calls - total | 2 |
| Macro calls - unresolved | 0 |
| Taint edges - number of edges | 2 |
| Taint edges - number of edges | 3 |
| Taint reach - nodes tainted | 0 |
| Taint reach - per million nodes | 0 |
| Taint sinks - cryptographic operations | 0 |
| Taint sinks - query sinks | 0 |
| Taint sinks - query sinks | 1 |
| Taint sources - active | 0 |
| Taint sources - disabled | 0 |
| Taint sources - sensitive data | 0 |

View File

@@ -14,11 +14,11 @@
| Macro calls - resolved | 2 |
| Macro calls - total | 2 |
| Macro calls - unresolved | 0 |
| Taint edges - number of edges | 2 |
| Taint edges - number of edges | 3 |
| Taint reach - nodes tainted | 0 |
| Taint reach - per million nodes | 0 |
| Taint sinks - cryptographic operations | 0 |
| Taint sinks - query sinks | 0 |
| Taint sinks - query sinks | 1 |
| Taint sources - active | 0 |
| Taint sources - disabled | 0 |
| Taint sources - sensitive data | 0 |

View File

@@ -14,11 +14,11 @@
| Macro calls - resolved | 2 |
| Macro calls - total | 2 |
| Macro calls - unresolved | 0 |
| Taint edges - number of edges | 2 |
| Taint edges - number of edges | 3 |
| Taint reach - nodes tainted | 0 |
| Taint reach - per million nodes | 0 |
| Taint sinks - cryptographic operations | 0 |
| Taint sinks - query sinks | 0 |
| Taint sinks - query sinks | 1 |
| Taint sources - active | 0 |
| Taint sources - disabled | 0 |
| Taint sources - sensitive data | 0 |

View File

@@ -1,3 +1,7 @@
## 0.1.1
No user-facing changes.
## 0.1.0
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 0.1.1
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.1.0
lastReleaseVersion: 0.1.1

View File

@@ -73,6 +73,14 @@ query predicate multiplePositions(Element parent, int pos1, int pos2, string acc
pos1 != pos2
}
private import codeql.rust.elements.internal.PathResolution
/** Holds if `p` may resolve to multiple items including `i`. */
query predicate multiplePathResolutions(Path p, ItemNode i) {
i = resolvePath(p) and
strictcount(resolvePath(p)) > 1
}
/**
* Gets counts of abstract syntax tree inconsistencies of each type.
*/
@@ -98,4 +106,7 @@ int getAstInconsistencyCounts(string type) {
or
type = "Multiple positions" and
result = count(Element e | multiplePositions(_, _, _, _, e) | e)
or
type = "Multiple path resolutions" and
result = count(Path p | multiplePathResolutions(p, _) | p)
}

View File

@@ -4,3 +4,4 @@
private import codeql.rust.frameworks.rustcrypto.RustCrypto
private import codeql.rust.frameworks.Sqlx
private import codeql.rust.frameworks.stdlib.Clone

View File

@@ -1,263 +1,16 @@
private import rust
private import ControlFlowGraph
private import internal.SuccessorType
private import internal.ControlFlowGraphImpl as Impl
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private import internal.ControlFlowGraphImpl as CfgImpl
private import CfgImpl::BasicBlocks as BasicBlocksImpl
final class BasicBlock = BasicBlockImpl;
final class BasicBlock = BasicBlocksImpl::BasicBlock;
/**
* A basic block, that is, a maximal straight-line sequence of control flow nodes
* without branches or joins.
*/
private class BasicBlockImpl extends TBasicBlockStart {
/** Gets the CFG scope of this basic block. */
CfgScope getScope() { result = this.getAPredecessor().getScope() }
final class EntryBasicBlock = BasicBlocksImpl::EntryBasicBlock;
/** Gets an immediate successor of this basic block, if any. */
BasicBlock getASuccessor() { result = this.getASuccessor(_) }
final class ExitBasicBlock = BasicBlocksImpl::ExitBasicBlock;
/** Gets an immediate successor of this basic block of a given type, if any. */
BasicBlock getASuccessor(SuccessorType t) {
result.getFirstNode() = this.getLastNode().getASuccessor(t)
}
final class AnnotatedExitBasicBlock = BasicBlocksImpl::AnnotatedExitBasicBlock;
/** Gets an immediate predecessor of this basic block, if any. */
BasicBlock getAPredecessor() { result.getASuccessor() = this }
final class ConditionBasicBlock = BasicBlocksImpl::ConditionBasicBlock;
/** Gets an immediate predecessor of this basic block of a given type, if any. */
BasicBlock getAPredecessor(SuccessorType t) { result.getASuccessor(t) = this }
final class JoinBasicBlock = BasicBlocksImpl::JoinBasicBlock;
/** Gets the control flow node at a specific (zero-indexed) position in this basic block. */
CfgNode getNode(int pos) { bbIndex(this.getFirstNode(), result, pos) }
/** Gets a control flow node in this basic block. */
CfgNode getANode() { result = this.getNode(_) }
/** Gets the first control flow node in this basic block. */
CfgNode getFirstNode() { this = TBasicBlockStart(result) }
/** Gets the last control flow node in this basic block. */
CfgNode getLastNode() { result = this.getNode(this.length() - 1) }
/** Gets the length of this basic block. */
int length() { result = strictcount(this.getANode()) }
predicate immediatelyDominates(BasicBlock bb) { bbIDominates(this, bb) }
predicate strictlyDominates(BasicBlock bb) { bbIDominates+(this, bb) }
predicate dominates(BasicBlock bb) {
bb = this or
this.strictlyDominates(bb)
}
predicate inDominanceFrontier(BasicBlock df) {
this.dominatesPredecessor(df) and
not this.strictlyDominates(df)
}
/**
* Holds if this basic block dominates a predecessor of `df`.
*/
private predicate dominatesPredecessor(BasicBlock df) { this.dominates(df.getAPredecessor()) }
BasicBlock getImmediateDominator() { bbIDominates(result, this) }
predicate strictlyPostDominates(BasicBlock bb) { bbIPostDominates+(this, bb) }
predicate postDominates(BasicBlock bb) {
this.strictlyPostDominates(bb) or
this = bb
}
/** Holds if this basic block is in a loop in the control flow graph. */
predicate inLoop() { this.getASuccessor+() = this }
/** Gets a textual representation of this basic block. */
string toString() { result = this.getFirstNode().toString() }
/** Gets the location of this basic block. */
Location getLocation() { result = this.getFirstNode().getLocation() }
}
cached
private module Cached {
/** Internal representation of basic blocks. */
cached
newtype TBasicBlock = TBasicBlockStart(CfgNode cfn) { startsBB(cfn) }
/** Holds if `cfn` starts a new basic block. */
private predicate startsBB(CfgNode cfn) {
not exists(cfn.getAPredecessor()) and exists(cfn.getASuccessor())
or
cfn.isJoin()
or
cfn.getAPredecessor().isBranch()
}
/**
* Holds if `succ` is a control flow successor of `pred` within
* the same basic block.
*/
private predicate intraBBSucc(CfgNode pred, CfgNode succ) {
succ = pred.getASuccessor() and
not startsBB(succ)
}
/**
* Holds if `cfn` is the `i`th node in basic block `bb`.
*
* In other words, `i` is the shortest distance from a node `bb`
* that starts a basic block to `cfn` along the `intraBBSucc` relation.
*/
cached
predicate bbIndex(CfgNode bbStart, CfgNode cfn, int i) =
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfn, i)
/**
* Holds if the first node of basic block `succ` is a control flow
* successor of the last node of basic block `pred`.
*/
private predicate succBB(BasicBlock pred, BasicBlock succ) { succ = pred.getASuccessor() }
/** Holds if `dom` is an immediate dominator of `bb`. */
cached
predicate bbIDominates(BasicBlock dom, BasicBlock bb) =
idominance(entryBB/1, succBB/2)(_, dom, bb)
/** Holds if `pred` is a basic block predecessor of `succ`. */
private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) }
/** Holds if `bb` is an exit basic block that represents normal exit. */
private predicate normalExitBB(BasicBlock bb) {
bb.getANode().(Impl::AnnotatedExitNode).isNormal()
}
/** Holds if `dom` is an immediate post-dominator of `bb`. */
cached
predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) =
idominance(normalExitBB/1, predBB/2)(_, dom, bb)
/**
* Gets the `i`th predecessor of join block `jb`, with respect to some
* arbitrary order.
*/
cached
JoinBlockPredecessor getJoinBlockPredecessor(JoinBlock jb, int i) {
result =
rank[i + 1](JoinBlockPredecessor jbp |
jbp = jb.getAPredecessor()
|
jbp order by JoinBlockPredecessors::getId(jbp), JoinBlockPredecessors::getSplitString(jbp)
)
}
}
private import Cached
/** Holds if `bb` is an entry basic block. */
private predicate entryBB(BasicBlock bb) { bb.getFirstNode() instanceof Impl::EntryNode }
/**
* An entry basic block, that is, a basic block whose first node is
* an entry node.
*/
class EntryBasicBlock extends BasicBlockImpl {
EntryBasicBlock() { entryBB(this) }
override CfgScope getScope() {
this.getFirstNode() = any(Impl::EntryNode node | node.getScope() = result)
}
}
/**
* An annotated exit basic block, that is, a basic block whose last node is
* an annotated exit node.
*/
class AnnotatedExitBasicBlock extends BasicBlockImpl {
private boolean normal;
AnnotatedExitBasicBlock() {
exists(Impl::AnnotatedExitNode n |
n = this.getANode() and
if n.isNormal() then normal = true else normal = false
)
}
/** Holds if this block represent a normal exit. */
final predicate isNormal() { normal = true }
}
/**
* An exit basic block, that is, a basic block whose last node is
* an exit node.
*/
class ExitBasicBlock extends BasicBlockImpl {
ExitBasicBlock() { this.getLastNode() instanceof Impl::ExitNode }
}
private module JoinBlockPredecessors {
private predicate id(Raw::AstNode x, Raw::AstNode y) { x = y }
private predicate idOfDbAstNode(Raw::AstNode x, int y) = equivalenceRelation(id/2)(x, y)
// TODO: does not work if fresh ipa entities (`ipa: on:`) turn out to be first of the block
private predicate idOf(AstNode x, int y) { idOfDbAstNode(Synth::convertAstNodeToRaw(x), y) }
int getId(JoinBlockPredecessor jbp) {
idOf(jbp.getFirstNode().(Impl::AstCfgNode).getAstNode(), result)
or
idOf(jbp.(EntryBasicBlock).getScope(), result)
}
string getSplitString(JoinBlockPredecessor jbp) {
result = jbp.getFirstNode().(Impl::AstCfgNode).getSplitsString()
or
not exists(jbp.getFirstNode().(Impl::AstCfgNode).getSplitsString()) and
result = ""
}
}
/** A basic block with more than one predecessor. */
class JoinBlock extends BasicBlockImpl {
JoinBlock() { this.getFirstNode().isJoin() }
/**
* Gets the `i`th predecessor of this join block, with respect to some
* arbitrary order.
*/
JoinBlockPredecessor getJoinBlockPredecessor(int i) { result = getJoinBlockPredecessor(this, i) }
}
/** A basic block that is an immediate predecessor of a join block. */
class JoinBlockPredecessor extends BasicBlockImpl {
JoinBlockPredecessor() { this.getASuccessor() instanceof JoinBlock }
}
/** A basic block that terminates in a condition, splitting the subsequent control flow. */
class ConditionBlock extends BasicBlockImpl {
ConditionBlock() { this.getLastNode().isCondition() }
/**
* Holds if basic block `succ` is immediately controlled by this basic
* block with conditional value `s`. That is, `succ` is an immediate
* successor of this block, and `succ` can only be reached from
* the callable entry point by going via the `s` edge out of this basic block.
*/
pragma[nomagic]
predicate immediatelyControls(BasicBlock succ, SuccessorType s) {
succ = this.getASuccessor(s) and
forall(BasicBlock pred | pred = succ.getAPredecessor() and pred != this | succ.dominates(pred))
}
/**
* Holds if basic block `controlled` is controlled by this basic block with
* conditional value `s`. That is, `controlled` can only be reached from
* the callable entry point by going via the `s` edge out of this basic block.
*/
predicate controls(BasicBlock controlled, BooleanSuccessor s) {
exists(BasicBlock succ | this.immediatelyControls(succ, s) | succ.dominates(controlled))
}
}
final class JoinPredecessorBasicBlock = BasicBlocksImpl::JoinPredecessorBasicBlock;

View File

@@ -241,7 +241,7 @@ final class RecordExprCfgNode extends Nodes::RecordExprCfgNode {
exists(RecordExprField ref |
ref = node.getRecordExprFieldList().getAField() and
any(ChildMapping mapping).hasCfgChild(node, ref.getExpr(), this, result) and
field = ref.getNameRef().getText()
field = ref.getFieldName()
)
}
}
@@ -261,11 +261,12 @@ final class RecordPatCfgNode extends Nodes::RecordPatCfgNode {
RecordPatCfgNode() { node = this.getRecordPat() }
/** Gets the record pattern for the field `field`. */
pragma[nomagic]
PatCfgNode getFieldPat(string field) {
exists(RecordPatField rpf |
rpf = node.getRecordPatFieldList().getAField() and
any(ChildMapping mapping).hasCfgChild(node, rpf.getPat(), this, result) and
field = rpf.getNameRef().getText()
field = rpf.getFieldName()
)
}
}

View File

@@ -1,11 +1,8 @@
/** Provides classes representing the control flow graph. */
private import rust
private import internal.ControlFlowGraphImpl
private import internal.Completion
private import internal.SuccessorType
private import internal.Scope as Scope
private import BasicBlocks
final class CfgScope = Scope::CfgScope;
@@ -25,30 +22,4 @@ final class ContinueSuccessor = ContinueSuccessorImpl;
final class ReturnSuccessor = ReturnSuccessorImpl;
/**
* A control flow node.
*
* A control flow node is a node in the control flow graph (CFG). There is a
* many-to-one relationship between CFG nodes and AST nodes.
*
* Only nodes that can be reached from an entry point are included in the CFG.
*/
final class CfgNode extends Node {
/** Gets the file of this control flow node. */
File getFile() { result = this.getLocation().getFile() }
/** Gets a successor node of a given type, if any. */
CfgNode getASuccessor(SuccessorType t) { result = super.getASuccessor(t) }
/** Gets an immediate successor, if any. */
CfgNode getASuccessor() { result = this.getASuccessor(_) }
/** Gets an immediate predecessor node of a given flow type, if any. */
CfgNode getAPredecessor(SuccessorType t) { result.getASuccessor(t) = this }
/** Gets an immediate predecessor, if any. */
CfgNode getAPredecessor() { result = this.getAPredecessor(_) }
/** Gets the basic block that this control flow node belongs to. */
BasicBlock getBasicBlock() { result.getANode() = this }
}
final class CfgNode = Node;

View File

@@ -3,6 +3,8 @@ import codeql.controlflow.Cfg
import Completion
private import Scope as Scope
private import codeql.rust.controlflow.ControlFlowGraph as Cfg
private import codeql.rust.elements.internal.generated.Raw
private import codeql.rust.elements.internal.generated.Synth
private module CfgInput implements InputSig<Location> {
private import codeql.rust.internal.CachedStages
@@ -48,6 +50,15 @@ private module CfgInput implements InputSig<Location> {
/** Holds if `scope` is exited when `last` finishes with completion `c`. */
predicate scopeLast(CfgScope scope, AstNode last, Completion c) { scope.scopeLast(last, c) }
private predicate id(Raw::AstNode x, Raw::AstNode y) { x = y }
private predicate idOfDbAstNode(Raw::AstNode x, int y) = equivalenceRelation(id/2)(x, y)
// TODO: does not work if fresh ipa entities (`ipa: on:`) turn out to be first of the block
int idOfAstNode(AstNode node) { idOfDbAstNode(Synth::convertAstNodeToRaw(node), result) }
int idOfCfgScope(CfgScope node) { result = idOfAstNode(node) }
}
private module CfgSplittingInput implements SplittingInputSig<Location, CfgInput> {

View File

@@ -13,23 +13,18 @@ private import DataFlowImpl::Node as Node
* (inter-procedural) data flow analyses.
*/
module DataFlow {
final class Node = Node::Node;
final class Node = Node::NodePublic;
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
final class ParameterNode extends Node instanceof Node::SourceParameterNode {
/** Gets the parameter that this node corresponds to. */
ParamBase getParameter() { result = super.getParameter().getParamBase() }
}
final class ParameterNode extends Node instanceof Node::SourceParameterNode { }
final class PostUpdateNode = Node::PostUpdateNode;
final class PostUpdateNode = Node::PostUpdateNodePublic;
final class Content = DataFlowImpl::Content;
final class VariantContent = DataFlowImpl::VariantContent;
final class ContentSet = DataFlowImpl::ContentSet;
/**

View File

@@ -49,16 +49,12 @@ final class DataFlowCallable extends TDataFlowCallable {
}
final class DataFlowCall extends TDataFlowCall {
private CallExprBaseCfgNode call;
DataFlowCall() { this = TCall(call) }
/** Gets the underlying call in the CFG, if any. */
CallExprCfgNode asCallExprCfgNode() { result = call }
CallExprCfgNode asCallExprCfgNode() { result = this.asCallBaseExprCfgNode() }
MethodCallExprCfgNode asMethodCallExprCfgNode() { result = call }
MethodCallExprCfgNode asMethodCallExprCfgNode() { result = this.asCallBaseExprCfgNode() }
CallExprBaseCfgNode asCallBaseExprCfgNode() { result = call }
CallExprBaseCfgNode asCallBaseExprCfgNode() { this = TCall(result) }
predicate isSummaryCall(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
@@ -67,7 +63,7 @@ final class DataFlowCall extends TDataFlowCall {
}
DataFlowCallable getEnclosingCallable() {
result = TCfgScope(call.getExpr().getEnclosingCfgScope())
result = TCfgScope(this.asCallBaseExprCfgNode().getExpr().getEnclosingCfgScope())
or
exists(FlowSummaryImpl::Public::SummarizedCallable c |
this.isSummaryCall(c, _) and
@@ -132,12 +128,15 @@ private predicate isArgumentForCall(ExprCfgNode arg, CallExprBaseCfgNode call, P
arg = call.(MethodCallExprCfgNode).getReceiver() and pos.isSelf()
}
/**
* Provides the `Node` class and subclasses thereof.
*
* Classes with names ending in `Public` are exposed as `final` aliases in the
* public `DataFlow` API, so they should not expose internal implementation details.
*/
module Node {
/**
* An element, viewed as a node in a data flow graph. Either an expression
* (`ExprNode`) or a parameter (`ParameterNode`).
*/
abstract class Node extends TNode {
/** An element, viewed as a node in a data flow graph. */
abstract class NodePublic extends TNode {
/** Gets the location of this node. */
abstract Location getLocation();
@@ -149,11 +148,18 @@ module Node {
*/
ExprCfgNode asExpr() { none() }
/**
* Gets the parameter that corresponds to this node, if any.
*/
ParamBase asParameter() { result = this.(SourceParameterNode).getParameter().getParamBase() }
/**
* Gets the pattern that corresponds to this node, if any.
*/
PatCfgNode asPat() { none() }
}
abstract class Node extends NodePublic {
/** Gets the enclosing callable. */
DataFlowCallable getEnclosingCallable() { result = TCfgScope(this.getCfgScope()) }
@@ -164,11 +170,6 @@ module Node {
* Gets the control flow node that corresponds to this data flow node.
*/
CfgNode getCfgNode() { none() }
/**
* Gets this node's underlying SSA definition, if any.
*/
Ssa::Definition asDefinition() { none() }
}
/** A node type that is not implemented. */
@@ -277,6 +278,7 @@ module Node {
* flow graph.
*/
abstract class ParameterNode extends Node {
/** Holds if this node is a parameter of `c` at position `pos`. */
abstract predicate isParameterOf(DataFlowCallable c, ParameterPosition pos);
}
@@ -466,10 +468,12 @@ module Node {
* Nodes corresponding to AST elements, for example `ExprNode`, usually refer
* to the value before the update.
*/
abstract class PostUpdateNode extends Node {
abstract class PostUpdateNodePublic extends NodePublic {
/** Gets the node before the state update. */
abstract Node getPreUpdateNode();
abstract NodePublic getPreUpdateNode();
}
abstract class PostUpdateNode extends PostUpdateNodePublic, Node {
override string toString() { result = "[post] " + this.getPreUpdateNode().toString() }
}
@@ -605,46 +609,124 @@ module LocalFlow {
}
}
private import codeql.util.Option
/**
* Provides temporary modeling of built-in variants, for which no source code
* `Item`s are available.
*
* TODO: Remove once library code is extracted.
*/
private module VariantInLib {
private import codeql.util.Option
private class CrateOrigin extends string {
CrateOrigin() {
this = [any(Item i).getCrateOrigin(), any(Resolvable r).getResolvedCrateOrigin()]
private class CrateOrigin extends string {
CrateOrigin() { this = any(Resolvable r).getResolvedCrateOrigin() }
}
private class CrateOriginOption = Option<CrateOrigin>::Option;
private CrateOriginOption langCoreCrate() { result.asSome() = "lang:core" }
private newtype TVariantInLib =
MkVariantInLib(CrateOriginOption crate, string path, string name) {
crate = langCoreCrate() and
(
path = "crate::option::Option" and
name = "Some"
or
path = "crate::result::Result" and
name = ["Ok", "Err"]
)
}
/** An enum variant from library code, represented by the enum's canonical path and the variant's name. */
class VariantInLib extends MkVariantInLib {
CrateOriginOption crate;
string path;
string name;
VariantInLib() { this = MkVariantInLib(crate, path, name) }
int getAPosition() {
this = MkVariantInLib(langCoreCrate(), "crate::option::Option", "Some") and
result = 0
or
this = MkVariantInLib(langCoreCrate(), "crate::result::Result", ["Ok", "Err"]) and
result = 0
}
string getExtendedCanonicalPath() { result = path + "::" + name }
string toString() { result = name }
}
/** A tuple variant from library code. */
class VariantInLibTupleFieldContent extends Content, TVariantInLibTupleFieldContent {
private VariantInLib::VariantInLib v;
private int pos_;
VariantInLibTupleFieldContent() { this = TVariantInLibTupleFieldContent(v, pos_) }
VariantInLib::VariantInLib getVariantInLib(int pos) { result = v and pos = pos_ }
string getExtendedCanonicalPath() { result = v.getExtendedCanonicalPath() }
int getPosition() { result = pos_ }
final override string toString() {
// only print indices when the arity is > 1
if exists(TVariantInLibTupleFieldContent(v, 1))
then result = v.toString() + "(" + pos_ + ")"
else result = v.toString()
}
final override Location getLocation() { result instanceof EmptyLocation }
}
pragma[nomagic]
private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption crate, string path) {
path = r.getResolvedPath() and
(
crate.asSome() = r.getResolvedCrateOrigin()
or
crate.isNone() and
not r.hasResolvedCrateOrigin()
)
}
/** Holds if path `p` resolves to variant `v`. */
private predicate pathResolveToVariantInLib(PathAstNode p, VariantInLib v) {
exists(CrateOriginOption crate, string path, string name |
resolveExtendedCanonicalPath(p, pragma[only_bind_into](crate), path + "::" + name) and
v = MkVariantInLib(pragma[only_bind_into](crate), path, name)
)
}
/** Holds if `p` destructs an enum variant `v`. */
pragma[nomagic]
private predicate tupleVariantCanonicalDestruction(TupleStructPat p, VariantInLib v) {
pathResolveToVariantInLib(p, v)
}
bindingset[pos]
predicate tupleVariantCanonicalDestruction(
TupleStructPat pat, VariantInLibTupleFieldContent c, int pos
) {
tupleVariantCanonicalDestruction(pat, c.getVariantInLib(pos))
}
/** Holds if `ce` constructs an enum value of type `v`. */
pragma[nomagic]
private predicate tupleVariantCanonicalConstruction(CallExpr ce, VariantInLib v) {
pathResolveToVariantInLib(ce.getFunction().(PathExpr), v)
}
bindingset[pos]
predicate tupleVariantCanonicalConstruction(CallExpr ce, VariantInLibTupleFieldContent c, int pos) {
tupleVariantCanonicalConstruction(ce, c.getVariantInLib(pos))
}
}
private class CrateOriginOption = Option<CrateOrigin>::Option;
pragma[nomagic]
private predicate hasExtendedCanonicalPath(Item i, CrateOriginOption crate, string path) {
path = i.getExtendedCanonicalPath() and
(
crate.asSome() = i.getCrateOrigin()
or
crate.isNone() and
not i.hasCrateOrigin()
)
}
pragma[nomagic]
private predicate variantHasExtendedCanonicalPath(
Enum e, Variant v, CrateOriginOption crate, string path, string name
) {
hasExtendedCanonicalPath(e, crate, path) and
v = e.getVariantList().getAVariant() and
name = v.getName().getText()
}
pragma[nomagic]
private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption crate, string path) {
path = r.getResolvedPath() and
(
crate.asSome() = r.getResolvedCrateOrigin()
or
crate.isNone() and
not r.hasResolvedCrateOrigin()
)
}
class VariantInLibTupleFieldContent = VariantInLib::VariantInLibTupleFieldContent;
/**
* A path to a value contained in an object. For example a field name of a struct.
@@ -652,93 +734,78 @@ private predicate resolveExtendedCanonicalPath(Resolvable r, CrateOriginOption c
abstract class Content extends TContent {
/** Gets a textual representation of this content. */
abstract string toString();
/** Gets the location of this content. */
abstract Location getLocation();
}
/** A canonical path pointing to an enum variant. */
class VariantCanonicalPath extends MkVariantCanonicalPath {
CrateOriginOption crate;
string path;
string name;
VariantCanonicalPath() { this = MkVariantCanonicalPath(crate, path, name) }
/** Gets the underlying variant. */
Variant getVariant() { variantHasExtendedCanonicalPath(_, result, crate, path, name) }
string getExtendedCanonicalPath() { result = path + "::" + name }
string toString() { result = name }
Location getLocation() { result = this.getVariant().getLocation() }
/** A field belonging to either a variant or a struct. */
abstract class FieldContent extends Content {
/** Gets an access to this field. */
pragma[nomagic]
abstract FieldExprCfgNode getAnAccess();
}
/**
* A variant of an `enum`. In addition to the variant itself, this also includes the
* position (for tuple variants) or the field name (for record variants).
*/
abstract class VariantContent extends Content { }
/** A tuple field belonging to either a variant or a struct. */
class TupleFieldContent extends FieldContent, TTupleFieldContent {
private TupleField field;
/** A tuple variant. */
private class VariantPositionContent extends VariantContent, TVariantPositionContent {
private VariantCanonicalPath v;
private int pos_;
TupleFieldContent() { this = TTupleFieldContent(field) }
VariantPositionContent() { this = TVariantPositionContent(v, pos_) }
predicate isVariantField(Variant v, int pos) { field.isVariantField(v, pos) }
VariantCanonicalPath getVariantCanonicalPath(int pos) { result = v and pos = pos_ }
predicate isStructField(Struct s, int pos) { field.isStructField(s, pos) }
override FieldExprCfgNode getAnAccess() { none() } // TODO
final override string toString() {
// only print indices when the arity is > 1
if exists(TVariantPositionContent(v, 1))
then result = v.toString() + "(" + pos_ + ")"
else result = v.toString()
exists(Variant v, int pos, string vname |
this.isVariantField(v, pos) and
vname = v.getName().getText() and
// only print indices when the arity is > 1
if exists(v.getTupleField(1)) then result = vname + "(" + pos + ")" else result = vname
)
or
exists(Struct s, int pos, string sname |
this.isStructField(s, pos) and
sname = s.getName().getText() and
// only print indices when the arity is > 1
if exists(s.getTupleField(1)) then result = sname + "(" + pos + ")" else result = sname
)
}
final override Location getLocation() { result = field.getLocation() }
}
/** A record variant. */
private class VariantFieldContent extends VariantContent, TVariantFieldContent {
private VariantCanonicalPath v;
private string field_;
/** A record field belonging to either a variant or a struct. */
class RecordFieldContent extends FieldContent, TRecordFieldContent {
private RecordField field;
VariantFieldContent() { this = TVariantFieldContent(v, field_) }
RecordFieldContent() { this = TRecordFieldContent(field) }
VariantCanonicalPath getVariantCanonicalPath(string field) { result = v and field = field_ }
predicate isVariantField(Variant v, string name) { field.isVariantField(v, name) }
predicate isStructField(Struct s, string name) { field.isStructField(s, name) }
override FieldExprCfgNode getAnAccess() { none() } // TODO
final override string toString() {
// only print field when the arity is > 1
if strictcount(string f | exists(TVariantFieldContent(v, f))) > 1
then result = v.toString() + "{" + field_ + "}"
else result = v.toString()
exists(Variant v, string name, string vname |
this.isVariantField(v, name) and
vname = v.getName().getText() and
// only print field when the arity is > 1
if strictcount(v.getRecordField(_)) > 1 then result = vname + "." + name else result = vname
)
or
exists(Struct s, string name, string sname |
this.isStructField(s, name) and
sname = s.getName().getText() and
// only print field when the arity is > 1
if strictcount(s.getRecordField(_)) > 1 then result = sname + "." + name else result = sname
)
}
}
/** A canonical path pointing to a struct. */
class StructCanonicalPath extends MkStructCanonicalPath {
CrateOriginOption crate;
string path;
StructCanonicalPath() { this = MkStructCanonicalPath(crate, path) }
/** Gets the underlying struct. */
Struct getStruct() { hasExtendedCanonicalPath(result, crate, path) }
string getExtendedCanonicalPath() { result = path }
string toString() { result = this.getStruct().getName().getText() }
Location getLocation() { result = this.getStruct().getLocation() }
}
/** Content stored in a field on a struct. */
private class StructFieldContent extends Content, TStructFieldContent {
private StructCanonicalPath s;
private string field_;
StructFieldContent() { this = TStructFieldContent(s, field_) }
StructCanonicalPath getStructCanonicalPath(string field) { result = s and field = field_ }
override string toString() { result = s.toString() + "." + field_.toString() }
final override Location getLocation() { result = field.getLocation() }
}
/** A captured variable. */
@@ -751,20 +818,29 @@ private class CapturedVariableContent extends Content, TCapturedVariableContent
Variable getVariable() { result = v }
override string toString() { result = "captured " + v }
override Location getLocation() { result = v.getLocation() }
}
/** A value referred to by a reference. */
final class ReferenceContent extends Content, TReferenceContent {
override string toString() { result = "&ref" }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* An element in an array.
* An element in a collection where we do not track the specific collection
* type nor the placement of the element in the collection. Therefore the
* collection should be one where the elements are reasonably homogeneous,
* i.e., if one is tainted all elements are considered tainted.
*
* Examples include the elements of a set, array, vector, or stack.
*/
final class ArrayElementContent extends Content, TArrayElement {
ArrayElementContent() { this = TArrayElement() }
final class ElementContent extends Content, TElementContent {
override string toString() { result = "element" }
override string toString() { result = "array[]" }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
@@ -773,19 +849,51 @@ final class ArrayElementContent extends Content, TArrayElement {
* NOTE: Unlike `struct`s and `enum`s tuples are structural and not nominal,
* hence we don't store a canonical path for them.
*/
private class TuplePositionContent extends Content, TTuplePositionContent {
final class TuplePositionContent extends FieldContent, TTuplePositionContent {
private int pos;
TuplePositionContent() { this = TTuplePositionContent(pos) }
int getPosition() { result = pos }
override FieldExprCfgNode getAnAccess() {
// TODO: limit to tuple types
result.getNameRef().getText().toInt() = pos
}
override string toString() { result = "tuple." + pos.toString() }
override Location getLocation() { result instanceof EmptyLocation }
}
/** Holds if `access` indexes a tuple at an index corresponding to `c`. */
private predicate fieldTuplePositionContent(FieldExprCfgNode access, TuplePositionContent c) {
access.getNameRef().getText().toInt() = c.getPosition()
/**
* A content for the index of an argument to at function call.
*
* Used by the model generator to create flow summaries for higher-order
* functions.
*/
final class FunctionCallArgumentContent extends Content, TFunctionCallArgumentContent {
private int pos;
FunctionCallArgumentContent() { this = TFunctionCallArgumentContent(pos) }
int getPosition() { result = pos }
override string toString() { result = "function argument at " + pos }
override Location getLocation() { result instanceof EmptyLocation }
}
/**
* A content for the return value of function call.
*
* Used by the model generator to create flow summaries for higher-order
* functions.
*/
final class FunctionCallReturnContent extends Content, TFunctionCallReturnContent {
override string toString() { result = "function return" }
override Location getLocation() { result instanceof EmptyLocation }
}
/** A value that represents a set of `Content`s. */
@@ -858,12 +966,13 @@ private module Aliases {
module RustDataFlow implements InputSig<Location> {
private import Aliases
private import codeql.rust.dataflow.DataFlow
/**
* An element, viewed as a node in a data flow graph. Either an expression
* (`ExprNode`) or a parameter (`ParameterNode`).
*/
final class Node = Node::Node;
class Node = DataFlow::Node;
final class ParameterNode = Node::ParameterNode;
@@ -873,7 +982,7 @@ module RustDataFlow implements InputSig<Location> {
final class OutNode = Node::OutNode;
final class PostUpdateNode = Node::PostUpdateNode;
class PostUpdateNode = DataFlow::PostUpdateNode;
final class CastNode = Node::NaNode;
@@ -887,7 +996,9 @@ module RustDataFlow implements InputSig<Location> {
n.isArgumentOf(call, pos)
}
DataFlowCallable nodeGetEnclosingCallable(Node node) { result = node.getEnclosingCallable() }
DataFlowCallable nodeGetEnclosingCallable(Node node) {
result = node.(Node::Node).getEnclosingCallable()
}
DataFlowType getNodeType(Node node) { any() }
@@ -902,9 +1013,9 @@ module RustDataFlow implements InputSig<Location> {
}
predicate neverSkipInPathGraph(Node node) {
node.getCfgNode() = any(LetStmtCfgNode s).getPat()
node.(Node::Node).getCfgNode() = any(LetStmtCfgNode s).getPat()
or
node.getCfgNode() = any(AssignmentExprCfgNode a).getLhs()
node.(Node::Node).getCfgNode() = any(AssignmentExprCfgNode a).getLhs()
or
exists(MatchExprCfgNode match |
node.asExpr() = match.getScrutinee() or
@@ -1007,40 +1118,6 @@ module RustDataFlow implements InputSig<Location> {
node2.(Node::FlowSummaryNode).getSummaryNode())
}
/** Holds if path `p` resolves to struct `s`. */
private predicate pathResolveToStructCanonicalPath(PathAstNode p, StructCanonicalPath s) {
exists(CrateOriginOption crate, string path |
resolveExtendedCanonicalPath(p, crate, path) and
s = MkStructCanonicalPath(crate, path)
)
}
/** Holds if path `p` resolves to variant `v`. */
private predicate pathResolveToVariantCanonicalPath(PathAstNode p, VariantCanonicalPath v) {
exists(CrateOriginOption crate, string path, string name |
resolveExtendedCanonicalPath(p, pragma[only_bind_into](crate), path + "::" + name) and
v = MkVariantCanonicalPath(pragma[only_bind_into](crate), path, name)
)
}
/** Holds if `p` destructs an enum variant `v`. */
pragma[nomagic]
private predicate tupleVariantDestruction(TupleStructPat p, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(p, v)
}
/** Holds if `p` destructs an enum variant `v`. */
pragma[nomagic]
private predicate recordVariantDestruction(RecordPat p, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(p, v)
}
/** Holds if `p` destructs a struct `s`. */
pragma[nomagic]
private predicate structDestruction(RecordPat p, StructCanonicalPath s) {
pathResolveToStructCanonicalPath(p, s)
}
/**
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
* `node1` references an object with a content `c.getAReadContent()` whose
@@ -1050,9 +1127,11 @@ module RustDataFlow implements InputSig<Location> {
exists(Content c | c = cs.(SingletonContentSet).getContent() |
exists(TupleStructPatCfgNode pat, int pos |
pat = node1.asPat() and
tupleVariantDestruction(pat.getPat(),
c.(VariantPositionContent).getVariantCanonicalPath(pos)) and
node2.asPat() = pat.getField(pos)
|
c = TTupleFieldContent(pat.getTupleStructPat().getTupleField(pos))
or
VariantInLib::tupleVariantCanonicalDestruction(pat.getPat(), c, pos)
)
or
exists(TuplePatCfgNode pat, int pos |
@@ -1063,14 +1142,7 @@ module RustDataFlow implements InputSig<Location> {
or
exists(RecordPatCfgNode pat, string field |
pat = node1.asPat() and
(
// Pattern destructs a struct-like variant.
recordVariantDestruction(pat.getPat(),
c.(VariantFieldContent).getVariantCanonicalPath(field))
or
// Pattern destructs a struct.
structDestruction(pat.getPat(), c.(StructFieldContent).getStructCanonicalPath(field))
) and
c = TRecordFieldContent(pat.getRecordPat().getRecordField(field)) and
node2.asPat() = pat.getFieldPat(field)
)
or
@@ -1078,27 +1150,25 @@ module RustDataFlow implements InputSig<Location> {
node1.asPat().(RefPatCfgNode).getPat() = node2.asPat()
or
exists(FieldExprCfgNode access |
// Read of a tuple entry
fieldTuplePositionContent(access, c) and
// TODO: Handle read of a struct field.
node1.asExpr() = access.getExpr() and
node2.asExpr() = access
node2.asExpr() = access and
access = c.(FieldContent).getAnAccess()
)
or
exists(IndexExprCfgNode arr |
c instanceof ArrayElementContent and
c instanceof ElementContent and
node1.asExpr() = arr.getBase() and
node2.asExpr() = arr
)
or
exists(ForExprCfgNode for |
c instanceof ArrayElementContent and
c instanceof ElementContent and
node1.asExpr() = for.getIterable() and
node2.asPat() = for.getPat()
)
or
exists(SlicePatCfgNode pat |
c instanceof ArrayElementContent and
c instanceof ElementContent and
node1.asPat() = pat and
node2.asPat() = pat.getAPat()
)
@@ -1106,7 +1176,7 @@ module RustDataFlow implements InputSig<Location> {
exists(TryExprCfgNode try |
node1.asExpr() = try.getExpr() and
node2.asExpr() = try and
c.(VariantPositionContent).getVariantCanonicalPath(0).getExtendedCanonicalPath() =
c.(VariantInLibTupleFieldContent).getVariantInLib(0).getExtendedCanonicalPath() =
["crate::option::Option::Some", "crate::result::Result::Ok"]
)
or
@@ -1117,6 +1187,13 @@ module RustDataFlow implements InputSig<Location> {
node2.asExpr() = deref
)
or
// Read from function return
exists(DataFlowCall call |
lambdaCall(call, _, node1) and
call = node2.(OutNode).getCall(TNormalReturnKind()) and
c instanceof FunctionCallReturnContent
)
or
VariableCapture::readStep(node1, c, node2)
)
or
@@ -1124,51 +1201,29 @@ module RustDataFlow implements InputSig<Location> {
cs, node2.(Node::FlowSummaryNode).getSummaryNode())
}
/** Holds if `ce` constructs an enum value of type `v`. */
pragma[nomagic]
private predicate tupleVariantConstruction(CallExpr ce, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(ce.getFunction().(PathExpr), v)
}
/** Holds if `re` constructs an enum value of type `v`. */
pragma[nomagic]
private predicate recordVariantConstruction(RecordExpr re, VariantCanonicalPath v) {
pathResolveToVariantCanonicalPath(re, v)
}
/** Holds if `re` constructs a struct value of type `s`. */
pragma[nomagic]
private predicate structConstruction(RecordExpr re, StructCanonicalPath s) {
pathResolveToStructCanonicalPath(re, s)
}
private predicate tupleAssignment(Node node1, Node node2, TuplePositionContent c) {
private predicate fieldAssignment(Node node1, Node node2, FieldContent c) {
exists(AssignmentExprCfgNode assignment, FieldExprCfgNode access |
assignment.getLhs() = access and
fieldTuplePositionContent(access, c) and
node1.asExpr() = assignment.getRhs() and
node2.asExpr() = access.getExpr()
node2.asExpr() = access.getExpr() and
access = c.getAnAccess()
)
}
pragma[nomagic]
private predicate storeContentStep(Node node1, Content c, Node node2) {
exists(CallExprCfgNode call, int pos |
tupleVariantConstruction(call.getCallExpr(),
c.(VariantPositionContent).getVariantCanonicalPath(pos)) and
node1.asExpr() = call.getArgument(pos) and
node1.asExpr() = call.getArgument(pragma[only_bind_into](pos)) and
node2.asExpr() = call
|
c = TTupleFieldContent(call.getCallExpr().getTupleField(pragma[only_bind_into](pos)))
or
VariantInLib::tupleVariantCanonicalConstruction(call.getCallExpr(), c, pos)
)
or
exists(RecordExprCfgNode re, string field |
(
// Expression is for a struct-like enum variant.
recordVariantConstruction(re.getRecordExpr(),
c.(VariantFieldContent).getVariantCanonicalPath(field))
or
// Expression is for a struct.
structConstruction(re.getRecordExpr(), c.(StructFieldContent).getStructCanonicalPath(field))
) and
c = TRecordFieldContent(re.getRecordExpr().getRecordField(field)) and
node1.asExpr() = re.getFieldExpr(field) and
node2.asExpr() = re
)
@@ -1178,17 +1233,17 @@ module RustDataFlow implements InputSig<Location> {
node2.asExpr() = tuple
)
or
c instanceof ArrayElementContent and
c instanceof ElementContent and
node1.asExpr() =
[
node2.asExpr().(ArrayRepeatExprCfgNode).getRepeatOperand(),
node2.asExpr().(ArrayListExprCfgNode).getAnExpr()
]
or
tupleAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
fieldAssignment(node1, node2.(PostUpdateNode).getPreUpdateNode(), c)
or
exists(AssignmentExprCfgNode assignment, IndexExprCfgNode index |
c instanceof ArrayElementContent and
c instanceof ElementContent and
assignment.getLhs() = index and
node1.asExpr() = assignment.getRhs() and
node2.(PostUpdateNode).getPreUpdateNode().asExpr() = index.getBase()
@@ -1200,6 +1255,13 @@ module RustDataFlow implements InputSig<Location> {
node2.asExpr() = ref
)
or
// Store in function argument
exists(DataFlowCall call, int i |
isArgumentNode(node1, call, TPositionalParameterPosition(i)) and
lambdaCall(call, _, node2.(PostUpdateNode).getPreUpdateNode()) and
c.(FunctionCallArgumentContent).getPosition() = i
)
or
VariableCapture::storeStep(node1, c, node2)
}
@@ -1221,7 +1283,7 @@ module RustDataFlow implements InputSig<Location> {
* in `x.f = newValue`.
*/
predicate clearsContent(Node n, ContentSet cs) {
tupleAssignment(_, n, cs.(SingletonContentSet).getContent())
fieldAssignment(_, n, cs.(SingletonContentSet).getContent())
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(Node::FlowSummaryNode).getSummaryNode(),
cs)
@@ -1295,10 +1357,14 @@ module RustDataFlow implements InputSig<Location> {
* invoked expression.
*/
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
receiver.asExpr() = call.asCallExprCfgNode().getFunction() and
// All calls to complex expressions and local variable accesses are lambda call.
exists(Expr f | f = receiver.asExpr().getExpr() |
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
(
receiver.asExpr() = call.asCallExprCfgNode().getFunction() and
// All calls to complex expressions and local variable accesses are lambda call.
exists(Expr f | f = receiver.asExpr().getExpr() |
f instanceof PathExpr implies f = any(Variable v).getAnAccess()
)
or
call.isSummaryCall(_, receiver.(Node::FlowSummaryNode).getSummaryNode())
) and
exists(kind)
}
@@ -1521,47 +1587,13 @@ private module Cached {
cached
newtype TReturnKind = TNormalReturnKind()
private CrateOriginOption langCoreCrate() { result.asSome() = "lang:core" }
cached
newtype TVariantCanonicalPath =
MkVariantCanonicalPath(CrateOriginOption crate, string path, string name) {
variantHasExtendedCanonicalPath(_, _, crate, path, name)
or
// TODO: Remove once library types are extracted
crate = langCoreCrate() and
(
path = "crate::option::Option" and
name = "Some"
or
path = "crate::result::Result" and
name = ["Ok", "Err"]
)
}
cached
newtype TStructCanonicalPath =
MkStructCanonicalPath(CrateOriginOption crate, string path) {
exists(Struct s | hasExtendedCanonicalPath(s, crate, path))
}
cached
newtype TContent =
TVariantPositionContent(VariantCanonicalPath v, int pos) {
pos in [0 .. v.getVariant().getFieldList().(TupleFieldList).getNumberOfFields() - 1]
or
// TODO: Remove once library types are extracted
v = MkVariantCanonicalPath(langCoreCrate(), "crate::option::Option", "Some") and
pos = 0
or
// TODO: Remove once library types are extracted
v = MkVariantCanonicalPath(langCoreCrate(), "crate::result::Result", ["Ok", "Err"]) and
pos = 0
} or
TVariantFieldContent(VariantCanonicalPath v, string field) {
field = v.getVariant().getFieldList().(RecordFieldList).getAField().getName().getText()
} or
TArrayElement() or
TTupleFieldContent(TupleField field) or
TRecordFieldContent(RecordField field) or
// TODO: Remove once library types are extracted
TVariantInLibTupleFieldContent(VariantInLib::VariantInLib v, int pos) { pos = v.getAPosition() } or
TElementContent() or
TTuplePositionContent(int pos) {
pos in [0 .. max([
any(TuplePat pat).getNumberOfFields(),
@@ -1569,8 +1601,9 @@ private module Cached {
]
)]
} or
TStructFieldContent(StructCanonicalPath s, string field) {
field = s.getStruct().getFieldList().(RecordFieldList).getAField().getName().getText()
TFunctionCallReturnContent() or
TFunctionCallArgumentContent(int pos) {
pos in [0 .. any(CallExpr c).getArgList().getNumberOfArgs() - 1]
} or
TCapturedVariableContent(VariableCapture::CapturedVariable v) or
TReferenceContent()

View File

@@ -51,7 +51,7 @@ module Input implements InputSig<Location, RustDataFlow> {
override MethodCallExpr getCall() { result = call }
}
RustDataFlow::ArgumentPosition callbackSelfParameterPosition() { none() }
RustDataFlow::ArgumentPosition callbackSelfParameterPosition() { result.isClosureSelf() }
ReturnKind getStandardReturnValueKind() { result = TNormalReturnKind() }
@@ -61,26 +61,36 @@ module Input implements InputSig<Location, RustDataFlow> {
string encodeContent(ContentSet cs, string arg) {
exists(Content c | cs = TSingletonContentSet(c) |
exists(VariantCanonicalPath v | result = "Variant" |
exists(int pos |
c = TVariantPositionContent(v, pos) and
arg = v.getExtendedCanonicalPath() + "(" + pos + ")"
)
or
exists(string field |
c = TVariantFieldContent(v, field) and
arg = v.getExtendedCanonicalPath() + "::" + field
)
)
or
exists(StructCanonicalPath s, string field |
exists(Addressable a, int pos |
// TODO: calculate in QL
arg = a.getExtendedCanonicalPath() + "(" + pos + ")"
|
result = "Struct" and
c = TStructFieldContent(s, field) and
arg = s.getExtendedCanonicalPath() + "::" + field
c.(TupleFieldContent).isStructField(a, pos)
or
result = "Variant" and
c.(TupleFieldContent).isVariantField(a, pos)
)
or
result = "ArrayElement" and
c = TArrayElement() and
exists(Addressable a, string field |
// TODO: calculate in QL
arg = a.getExtendedCanonicalPath() + "::" + field
|
result = "Struct" and
c.(RecordFieldContent).isStructField(a, field)
or
result = "Variant" and
c.(RecordFieldContent).isVariantField(a, field)
)
or
result = "Variant" and
c =
any(VariantInLibTupleFieldContent v |
arg = v.getExtendedCanonicalPath() + "(" + v.getPosition() + ")"
)
or
result = "Element" and
c = TElementContent() and
arg = ""
or
exists(int pos |
@@ -127,12 +137,12 @@ private module StepsInput implements Impl::Private::StepsInputSig {
result.asCallBaseExprCfgNode().getCallExprBase() = sc.(LibraryCallable).getACall()
}
Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
RustDataFlow::Node getSourceNode(Input::SourceBase source, Impl::Private::SummaryComponent sc) {
sc = Impl::Private::SummaryComponent::return(_) and
result.asExpr().getExpr() = source.getCall()
}
Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
RustDataFlow::Node getSinkNode(Input::SinkBase sink, Impl::Private::SummaryComponent sc) {
exists(CallExprBase call, Expr arg, ParameterPosition pos |
result.asExpr().getExpr() = arg and
sc = Impl::Private::SummaryComponent::argument(pos) and

View File

@@ -28,7 +28,7 @@
* - `Parameter[n]`: the `n`-th parameter of a callback. May be a range of form `x..y` (inclusive)
* and/or a comma-separated list.
* - `ReturnValue`: the value returned by a function call.
* - `ArrayElement`: an element of an array.
* - `Element`: an element in a collection.
* - `Variant[v::f]`: field `f` of the variant with canonical path `v`, for example
* `Variant[crate::ihex::Record::Data::value]`.
* - `Variant[v(i)]`: position `i` inside the variant with canonical path `v`, for example

View File

@@ -284,7 +284,7 @@ private predicate isControlFlowJump(Expr e) { e instanceof CallExprBase or e ins
private predicate capturedCallRead(Expr call, BasicBlock bb, int i, Variable v) {
isControlFlowJump(call) and
exists(Cfg::CfgScope scope |
hasCapturedRead(v, scope) and
hasCapturedRead(pragma[only_bind_into](v), pragma[only_bind_into](scope)) and
(
variableWriteInOuterScope(bb, any(int j | j < i), v, scope) or
variableWriteInOuterScope(bb.getAPredecessor+(), _, v, scope)
@@ -488,7 +488,7 @@ private module DataFlowIntegrationInput implements Impl::DataFlowIntegrationInpu
/** Holds if the guard `guard` controls block `bb` upon evaluating to `branch`. */
predicate guardControlsBlock(Guard guard, SsaInput::BasicBlock bb, boolean branch) {
exists(ConditionBlock conditionBlock, ConditionalSuccessor s |
exists(ConditionBasicBlock conditionBlock, ConditionalSuccessor s |
guard = conditionBlock.getLastNode() and
s.getValue() = branch and
conditionBlock.controls(bb, s)

View File

@@ -1,20 +1,21 @@
private import rust
private import codeql.dataflow.TaintTracking
private import codeql.rust.controlflow.CfgNodes
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.FlowSummary
private import DataFlowImpl
private import FlowSummaryImpl as FlowSummaryImpl
private import codeql.rust.internal.CachedStages
module RustTaintTracking implements InputSig<Location, RustDataFlow> {
predicate defaultTaintSanitizer(Node::Node node) { none() }
predicate defaultTaintSanitizer(DataFlow::Node node) { none() }
/**
* Holds if the additional step from `pred` to `succ` should be included in all
* global taint flow configurations.
*/
cached
predicate defaultAdditionalTaintStep(Node::Node pred, Node::Node succ, string model) {
predicate defaultAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ, string model) {
Stages::DataFlowStage::ref() and
model = "" and
(
@@ -44,7 +45,7 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
// source is a collection.
exists(SingletonContentSet cs |
RustDataFlow::readStep(pred, cs, succ) and
cs.getContent() instanceof ArrayElementContent
cs.getContent() instanceof ElementContent
)
or
exists(FormatArgsExprCfgNode format | succ.asExpr() = format |
@@ -61,10 +62,10 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
* and inputs to additional taint steps.
*/
bindingset[node]
predicate defaultImplicitTaintRead(Node::Node node, ContentSet cs) {
predicate defaultImplicitTaintRead(DataFlow::Node node, ContentSet cs) {
exists(node) and
exists(Content c | c = cs.(SingletonContentSet).getContent() |
c instanceof ArrayElementContent or
c instanceof ElementContent or
c instanceof ReferenceContent
)
}
@@ -73,5 +74,5 @@ module RustTaintTracking implements InputSig<Location, RustDataFlow> {
* Holds if the additional step from `src` to `sink` should be considered in
* speculative taint flow exploration.
*/
predicate speculativeTaintStep(Node::Node src, Node::Node sink) { none() }
predicate speculativeTaintStep(DataFlow::Node src, DataFlow::Node sink) { none() }
}

View File

@@ -12,7 +12,10 @@ import codeql.rust.elements.UseTreeList
/**
* A UseTree. For example:
* ```rust
* todo!()
* use std::collections::HashMap;
* use std::collections::*;
* use std::collections::HashMap as MyHashMap;
* use std::collections::{self, HashMap, HashSet};
* ```
*/
final class UseTree = Impl::UseTree;

View File

@@ -16,6 +16,7 @@ module Impl {
private import codeql.rust.elements.internal.MethodCallExprImpl::Impl
private import codeql.rust.elements.internal.CallExprImpl::Impl
private import codeql.rust.elements.internal.PathExprImpl::Impl
private import codeql.rust.elements.internal.PathResolution
pragma[nomagic]
Resolvable getCallResolvable(CallExprBase call) {
@@ -33,6 +34,10 @@ module Impl {
* Gets the target callable of this call, if a unique such target can
* be statically resolved.
*/
Callable getStaticTarget() { getCallResolvable(this).resolvesAsItem(result) }
Callable getStaticTarget() {
getCallResolvable(this).resolvesAsItem(result)
or
result = resolvePath(this.(CallExpr).getFunction().(PathExpr).getPath())
}
}
}

View File

@@ -12,6 +12,9 @@ private import codeql.rust.elements.PathExpr
* be referenced directly.
*/
module Impl {
private import rust
private import PathResolution as PathResolution
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A function call expression. For example:
@@ -24,5 +27,25 @@ module Impl {
*/
class CallExpr extends Generated::CallExpr {
override string toString() { result = this.getFunction().toAbbreviatedString() + "(...)" }
pragma[nomagic]
private PathResolution::ItemNode getResolvedFunction(int pos) {
result = PathResolution::resolvePath(this.getFunction().(PathExpr).getPath()) and
exists(this.getArgList().getArg(pos))
}
/**
* Gets the tuple field that matches the `pos`th argument of this call, if any.
*
* For example, if this call is `Option::Some(42)`, then the tuple field matching
* `42` is the first field of `Option::Some`.
*/
pragma[nomagic]
TupleField getTupleField(int pos) {
exists(PathResolution::ItemNode i | i = this.getResolvedFunction(pos) |
result.isStructField(i, pos) or
result.isVariantField(i, pos)
)
}
}
}

View File

@@ -27,5 +27,31 @@ module Impl {
then result = "...::" + this.getPart().toAbbreviatedString()
else result = this.getPart().toAbbreviatedString()
}
/**
* Gets the text of this path, if it exists.
*/
pragma[nomagic]
string getText() { result = this.getPart().getNameRef().getText() }
}
/** A simple identifier path. */
class IdentPath extends Path {
private string name;
IdentPath() {
not this.hasQualifier() and
exists(PathSegment ps |
ps = this.getPart() and
not ps.hasGenericArgList() and
not ps.hasParenthesizedArgList() and
not ps.hasPathType() and
not ps.hasReturnTypeSyntax() and
name = ps.getNameRef().getText()
)
}
/** Gets the identifier name. */
string getName() { result = name }
}
}

View File

@@ -0,0 +1,472 @@
/**
* Provides functionality for resolving paths, using the predicate `resolvePath`.
*/
private import rust
private import codeql.rust.elements.internal.generated.ParentChild
/**
* An item that may be referred to by a path, and which is a node in
* the _item graph_.
*
* The item graph is a labeled directed graph, where an edge
* `item1 --name--> item2` means that `item2` is available inside the
* scope of `item1` under the name `name`. For example, if we have
*
* ```rust
* mod m1 {
* mod m2 { }
* }
* ```
*
* then there is an edge `m1 --m2--> m1::m2`.
*
* Source files are also considered nodes in the item graph, and for
* each source file `f` there is an edge `f --name--> item` when `f`
* declares `item` with the name `name`.
*
* For imports like
*
* ```rust
* mod m1 {
* mod m2;
* use m2::foo;
* }
* ```
*
* we first generate an edge `m1::m2 --name--> f::item`, where `item` is
* any item (named `name`) inside the imported source file `f`. Using this
* edge, `m2::foo` can resolve to `f::foo`, which results in the edge
* `m1::use m2 --foo--> f::foo`. Lastly, all edges out of `use` nodes are
* lifted to predecessors in the graph, so we get an edge `m1 --foo--> f::foo`.
*
*
* References:
* - https://doc.rust-lang.org/reference/items/modules.html
* - https://doc.rust-lang.org/reference/names/scopes.html
* - https://doc.rust-lang.org/reference/paths.html
* - https://doc.rust-lang.org/reference/visibility-and-privacy.html
*/
abstract class ItemNode extends AstNode {
/** Gets the (original) name of this item. */
abstract string getName();
/** Gets the visibility of this item, if any. */
abstract Visibility getVisibility();
/** Holds if this item is declared as `pub`. */
bindingset[this]
pragma[inline_late]
predicate isPublic() { exists(this.getVisibility()) }
/** Gets an element that has this item as immediately enclosing item. */
pragma[nomagic]
Element getADescendant() {
getImmediateParent(result) = this
or
exists(Element mid |
mid = this.getADescendant() and
getImmediateParent(result) = mid and
not mid instanceof ItemNode
)
}
/** Gets the immediately enclosing item of this item, if any. */
pragma[nomagic]
ItemNode getImmediateParent() { this = result.getADescendant() }
/** Gets the immediately enclosing module (or source file) of this item. */
pragma[nomagic]
ModuleLikeNode getImmediateParentModule() { this = result.getAnItemInScope() }
pragma[nomagic]
private ItemNode getASuccessorRec(string name) {
sourceFileEdge(this, name, result)
or
this = result.getImmediateParent() and
name = result.getName()
or
fileImportEdge(this, name, result)
or
useImportEdge(this, name, result)
or
// items made available through `use` are available to nodes that contain the `use`
exists(UseItemNode use |
use = this.getASuccessorRec(_) and
result = use.(ItemNode).getASuccessorRec(name)
)
or
// items made available through macro calls are available to nodes that contain the macro call
exists(MacroCallItemNode call |
call = this.getASuccessorRec(_) and
result = call.(ItemNode).getASuccessorRec(name)
)
}
/** Gets a successor named `name` of this item, if any. */
pragma[nomagic]
ItemNode getASuccessor(string name) {
result = this.getASuccessorRec(name)
or
name = "super" and
if this instanceof Module
then result = this.getImmediateParentModule()
else result = this.getImmediateParentModule().getImmediateParentModule()
or
name = "self" and
not this instanceof Module and
result = this.getImmediateParentModule()
or
name = "Self" and
this = result.(ImplOrTraitItemNode).getAnItemInSelfScope()
or
name = "crate" and
result.(SourceFileItemNode).getFile() = this.getFile()
}
}
/** A module or a source file. */
abstract private class ModuleLikeNode extends ItemNode {
/** Gets an item that may refer directly to items defined in this module. */
pragma[nomagic]
ItemNode getAnItemInScope() {
result.getImmediateParent() = this
or
exists(ItemNode mid |
mid = this.getAnItemInScope() and
result.getImmediateParent() = mid and
not mid instanceof ModuleLikeNode
)
}
}
private class SourceFileItemNode extends ModuleLikeNode, SourceFile {
override string getName() { result = "(source file)" }
override Visibility getVisibility() { none() }
}
private class ConstItemNode extends ItemNode instanceof Const {
override string getName() { result = Const.super.getName().getText() }
override Visibility getVisibility() { result = Const.super.getVisibility() }
}
private class EnumItemNode extends ItemNode instanceof Enum {
override string getName() { result = Enum.super.getName().getText() }
override Visibility getVisibility() { result = Enum.super.getVisibility() }
}
private class VariantItemNode extends ItemNode instanceof Variant {
override string getName() { result = Variant.super.getName().getText() }
override Visibility getVisibility() { result = Variant.super.getVisibility() }
}
private class FunctionItemNode extends ItemNode instanceof Function {
override string getName() { result = Function.super.getName().getText() }
override Visibility getVisibility() { result = Function.super.getVisibility() }
}
abstract private class ImplOrTraitItemNode extends ItemNode {
/** Gets an item that may refer to this node using `Self`. */
pragma[nomagic]
ItemNode getAnItemInSelfScope() {
result.getImmediateParent() = this
or
exists(ItemNode mid |
mid = this.getAnItemInSelfScope() and
result.getImmediateParent() = mid and
not mid instanceof ImplOrTraitItemNode
)
}
}
private class ImplItemNode extends ImplOrTraitItemNode instanceof Impl {
override string getName() { result = "(impl)" }
override Visibility getVisibility() { result = Impl.super.getVisibility() }
}
private class MacroCallItemNode extends ItemNode instanceof MacroCall {
override string getName() { result = "(macro call)" }
override Visibility getVisibility() { none() }
}
private class ModuleItemNode extends ModuleLikeNode instanceof Module {
override string getName() { result = Module.super.getName().getText() }
override Visibility getVisibility() { result = Module.super.getVisibility() }
}
private class StructItemNode extends ItemNode instanceof Struct {
override string getName() { result = Struct.super.getName().getText() }
override Visibility getVisibility() { result = Struct.super.getVisibility() }
}
private class TraitItemNode extends ImplOrTraitItemNode instanceof Trait {
override string getName() { result = Trait.super.getName().getText() }
override Visibility getVisibility() { result = Trait.super.getVisibility() }
}
private class UnionItemNode extends ItemNode instanceof Union {
override string getName() { result = Union.super.getName().getText() }
override Visibility getVisibility() { result = Union.super.getVisibility() }
}
private class UseItemNode extends ItemNode instanceof Use {
override string getName() { result = "(use)" }
override Visibility getVisibility() { none() }
}
private class BlockExprItemNode extends ItemNode instanceof BlockExpr {
override string getName() { result = "(block expr)" }
override Visibility getVisibility() { none() }
}
private class TypeParamItemNode extends ItemNode instanceof TypeParam {
override string getName() { result = TypeParam.super.getName().getText() }
override Visibility getVisibility() { none() }
}
/** Holds if `item` has the name `name` and is a top-level item inside `f`. */
private predicate sourceFileEdge(SourceFile f, string name, ItemNode item) {
item = f.getAnItem() and
name = item.getName()
}
/** Holds if `f` is available as `mod name;` inside `folder`. */
private predicate fileModule(SourceFile f, string name, Folder folder) {
exists(File file | file = f.getFile() |
file.getBaseName() = name + ".rs" and
folder = file.getParentContainer()
or
exists(Folder encl |
file.getBaseName() = "mod.rs" and
encl = file.getParentContainer() and
name = encl.getBaseName() and
folder = encl.getParentContainer()
)
)
}
/**
* Holds if `m` is a `mod name;` module declaration happening in a file named
* `fileName.rs`, inside the folder `parent`.
*/
private predicate modImport(Module m, string fileName, string name, Folder parent) {
exists(File f |
f = m.getFile() and
not m.hasItemList() and
// TODO: handle
// ```
// #[path = "foo.rs"]
// mod bar;
// ```
not m.getAnAttr().getMeta().getPath().getText() = "path" and
name = m.getName().getText() and
parent = f.getParentContainer() and
fileName = f.getStem()
)
}
/** Holds if `m` is a `mod name;` item importing file `f`. */
private predicate fileImport(Module m, SourceFile f) {
exists(string fileName, string name, Folder parent | modImport(m, fileName, name, parent) |
// sibling import
fileModule(f, name, parent)
or
// child import
fileModule(f, name, parent.getFolder(fileName))
)
}
/**
* Holds if `mod` is a `mod name;` item targeting a file resulting in `item` being
* in scope under the name `name`.
*/
private predicate fileImportEdge(Module mod, string name, ItemNode item) {
item.isPublic() and
exists(SourceFile f |
fileImport(mod, f) and
sourceFileEdge(f, name, item)
)
}
private predicate useTreeDeclares(UseTree tree, string name) {
not tree.isGlob() and
not exists(tree.getUseTreeList()) and
(
name = tree.getRename().getName().getText() and
name != "_"
or
not tree.hasRename() and
name = tree.getPath().getText()
)
or
exists(UseTree mid |
useTreeDeclares(mid, name) and
mid = tree.getUseTreeList().getAUseTree()
)
}
/**
* Holds if `item` explicitly declares a sub item named `name`. This includes
* items declared by `use` statements, except for glob imports.
*/
pragma[nomagic]
private predicate declares(ItemNode item, string name) {
exists(ItemNode child | child.getImmediateParent() = item |
child.getName() = name
or
useTreeDeclares(child.(Use).getUseTree(), name)
)
or
exists(MacroCallItemNode call |
declares(call, name) and
call.getImmediateParent() = item
)
}
/** A path that does not access a local variable. */
private class RelevantPath extends Path {
RelevantPath() { not this = any(VariableAccess va).(PathExpr).getPath() }
pragma[nomagic]
predicate isUnqualified(string name) {
not exists(this.getQualifier()) and
not this = any(UseTreeList list).getAUseTree().getPath() and
name = this.getText()
}
}
/**
* Holds if the unqualified path `p` references an item named `name`, and `name`
* may be looked up inside enclosing item `encl`.
*/
pragma[nomagic]
private predicate unqualifiedPathLookup(RelevantPath p, string name, ItemNode encl) {
exists(ItemNode encl0 |
// lookup in the immediately enclosing item
p.isUnqualified(name) and
encl0.getADescendant() = p
or
// lookup in an outer scope, but only if the item is not declared in inner scope
exists(ItemNode mid |
unqualifiedPathLookup(p, name, mid) and
not declares(mid, name)
|
// nested modules do not have unqualified access to items from outer modules,
// except for items declared at top-level in the source file
if mid instanceof Module
then encl0.(SourceFileItemNode) = mid.getImmediateParent+()
else encl0 = mid.getImmediateParent()
)
|
// functions in `impl` blocks need to use explicit `Self::` to access other
// functions in the `impl` block
if encl0 instanceof ImplOrTraitItemNode then encl = encl0.getImmediateParent() else encl = encl0
)
}
/** Gets the item that `path` resolves to, if any. */
cached
ItemNode resolvePath(RelevantPath path) {
exists(ItemNode encl, string name |
unqualifiedPathLookup(path, name, encl) and
result = encl.getASuccessor(name)
)
or
exists(ItemNode q, string name |
q = resolvePathQualifier(path, name) and
result = q.getASuccessor(name)
)
or
result = resolveUseTreeListItem(_, _, path)
}
pragma[nomagic]
private ItemNode resolvePathQualifier(RelevantPath path, string name) {
result = resolvePath(path.getQualifier()) and
name = path.getText()
}
private predicate isUseTreeSubPath(UseTree tree, RelevantPath path) {
path = tree.getPath()
or
exists(RelevantPath mid |
isUseTreeSubPath(tree, mid) and
path = mid.getQualifier()
)
}
pragma[nomagic]
private predicate isUseTreeSubPathUnqualified(UseTree tree, RelevantPath path, string name) {
isUseTreeSubPath(tree, path) and
not exists(path.getQualifier()) and
name = path.getText()
}
pragma[nomagic]
private ItemNode resolveUseTreeListItem(Use use, UseTree tree, RelevantPath path) {
exists(UseTree midTree, ItemNode mid, string name |
mid = resolveUseTreeListItem(use, midTree) and
tree = midTree.getUseTreeList().getAUseTree() and
isUseTreeSubPathUnqualified(tree, path, pragma[only_bind_into](name)) and
result = mid.getASuccessor(pragma[only_bind_into](name))
)
or
exists(ItemNode q, string name |
q = resolveUseTreeListItemQualifier(use, tree, path, name) and
result = q.getASuccessor(name)
)
}
pragma[nomagic]
private ItemNode resolveUseTreeListItemQualifier(
Use use, UseTree tree, RelevantPath path, string name
) {
result = resolveUseTreeListItem(use, tree, path.getQualifier()) and
name = path.getText()
}
pragma[nomagic]
private ItemNode resolveUseTreeListItem(Use use, UseTree tree) {
tree = use.getUseTree() and
result = resolvePath(tree.getPath())
or
result = resolveUseTreeListItem(use, tree, tree.getPath())
}
/** Holds if `use` imports `item` as `name`. */
pragma[nomagic]
private predicate useImportEdge(Use use, string name, ItemNode item) {
exists(UseTree tree, ItemNode used |
used = resolveUseTreeListItem(use, tree) and
not exists(tree.getUseTreeList()) and
if tree.isGlob()
then
exists(ItemNode encl |
encl.getADescendant() = use and
item = used.getASuccessor(name) and
// glob imports can be shadowed
not declares(encl, name)
)
else item = used
|
not tree.hasRename() and
name = item.getName()
or
name = tree.getRename().getName().getText() and
name != "_"
)
}

View File

@@ -11,6 +11,9 @@ private import codeql.rust.elements.internal.generated.RecordExprField
* be referenced directly.
*/
module Impl {
private import rust
private import codeql.rust.elements.internal.PathImpl::Impl as PathImpl
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A field in a record expression. For example `a: 1` in:
@@ -24,7 +27,27 @@ module Impl {
private string toStringPart(int index) {
index = 0 and result = this.getNameRef().getText()
or
index = 1 and result = ": " + this.getExpr().toAbbreviatedString()
index = 1 and this.hasNameRef() and result = ": "
or
index = 2 and
result = this.getExpr().toAbbreviatedString()
}
/**
* Gets the name of the field. This includes the case when shorthand syntax is used:
*
* ```rust
* Foo {
* a: 1, // field name is `a`
* b // field name is `b`
* }
* ```
*/
string getFieldName() {
result = this.getNameRef().getText()
or
not this.hasNameRef() and
result = this.getExpr().(PathExpr).getPath().(PathImpl::IdentPath).getName()
}
}
}

View File

@@ -11,6 +11,9 @@ private import codeql.rust.elements.internal.generated.RecordExpr
* be referenced directly.
*/
module Impl {
private import rust
private import PathResolution as PathResolution
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A record expression. For example:
@@ -23,5 +26,17 @@ module Impl {
*/
class RecordExpr extends Generated::RecordExpr {
override string toString() { result = this.getPath().toString() + " {...}" }
/** Gets the record field that matches the `name` field of this record expression. */
pragma[nomagic]
RecordField getRecordField(string name) {
exists(PathResolution::ItemNode i |
i = PathResolution::resolvePath(this.getPath()) and
name = this.getRecordExprFieldList().getAField().getFieldName()
|
result.isStructField(i, name) or
result.isVariantField(i, name)
)
}
}
}

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `RecordField`.
*
@@ -12,11 +11,20 @@ private import codeql.rust.elements.internal.generated.RecordField
* be referenced directly.
*/
module Impl {
private import rust
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A RecordField. For example:
* ```rust
* todo!()
* ```
*/
class RecordField extends Generated::RecordField { }
class RecordField extends Generated::RecordField {
/** Holds if this record field is named `name` and belongs to the variant `v`. */
predicate isVariantField(Variant v, string name) { this = v.getRecordField(name) }
/** Holds if this record field is named `name` and belongs to the struct `s`. */
predicate isStructField(Struct s, string name) { this = s.getRecordField(name) }
}
}

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `RecordPatField`.
*
@@ -12,11 +11,42 @@ private import codeql.rust.elements.internal.generated.RecordPatField
* be referenced directly.
*/
module Impl {
private import rust
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A field in a record pattern. For example `a: 1` in:
* ```rust
* let Foo { a: 1, b: 2 } = foo;
* ```
*/
class RecordPatField extends Generated::RecordPatField { }
class RecordPatField extends Generated::RecordPatField {
override string toString() { result = concat(int i | | this.toStringPart(i) order by i) }
private string toStringPart(int index) {
index = 0 and result = this.getNameRef().getText()
or
index = 1 and this.hasNameRef() and result = ": "
or
index = 2 and
result = this.getPat().toAbbreviatedString()
}
/**
* Gets the name of the field. This includes the case when shorthand syntax is used:
*
* ```rust
* match foo {
* Foo { x: a, .. } => ..., // field name is `x`
* Bar { y, .. } => ... // field name is `y`
* }
* ```
*/
string getFieldName() {
result = this.getNameRef().getText()
or
not this.hasNameRef() and
result = this.getPat().(IdentPat).getName().getText()
}
}
}

View File

@@ -11,6 +11,9 @@ private import codeql.rust.elements.internal.generated.RecordPat
* be referenced directly.
*/
module Impl {
private import rust
private import PathResolution as PathResolution
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A record pattern. For example:
@@ -23,5 +26,17 @@ module Impl {
*/
class RecordPat extends Generated::RecordPat {
override string toString() { result = this.getPath().toAbbreviatedString() + " {...}" }
/** Gets the record field that matches the `name` pattern of this pattern. */
pragma[nomagic]
RecordField getRecordField(string name) {
exists(PathResolution::ItemNode i |
i = PathResolution::resolvePath(this.getPath()) and
name = this.getRecordPatFieldList().getAField().getFieldName()
|
result.isStructField(i, name) or
result.isVariantField(i, name)
)
}
}
}

View File

@@ -4,6 +4,7 @@
* INTERNAL: Do not use.
*/
private import rust
private import codeql.rust.elements.internal.generated.Struct
/**
@@ -20,5 +21,16 @@ module Impl {
*/
class Struct extends Generated::Struct {
override string toString() { result = "struct " + this.getName().getText() }
/** Gets the record field named `name`, if any. */
pragma[nomagic]
RecordField getRecordField(string name) {
result = this.getFieldList().(RecordFieldList).getAField() and
result.getName().getText() = name
}
/** Gets the `i`th tuple field, if any. */
pragma[nomagic]
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
}
}

View File

@@ -1,4 +1,3 @@
// generated by codegen, remove this comment if you wish to edit this file
/**
* This module provides a hand-modifiable wrapper around the generated class `TupleField`.
*
@@ -12,11 +11,20 @@ private import codeql.rust.elements.internal.generated.TupleField
* be referenced directly.
*/
module Impl {
private import rust
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A TupleField. For example:
* ```rust
* todo!()
* ```
*/
class TupleField extends Generated::TupleField { }
class TupleField extends Generated::TupleField {
/** Holds if this tuple field is the `pos`th field of variant `v`. */
predicate isVariantField(Variant v, int pos) { this = v.getTupleField(pos) }
/** Holds if this tuple field is the `pos`th field of struct `s`. */
predicate isStructField(Struct s, int pos) { this = s.getTupleField(pos) }
}
}

View File

@@ -11,6 +11,9 @@ private import codeql.rust.elements.internal.generated.TupleStructPat
* be referenced directly.
*/
module Impl {
private import rust
private import PathResolution as PathResolution
// the following QLdoc is generated: if you need to edit it, do it in the schema file
/**
* A tuple struct pattern. For example:
@@ -24,5 +27,20 @@ module Impl {
*/
class TupleStructPat extends Generated::TupleStructPat {
override string toString() { result = this.getPath().toAbbreviatedString() + "(...)" }
pragma[nomagic]
private PathResolution::ItemNode getResolvedPath(int pos) {
result = PathResolution::resolvePath(this.getPath()) and
exists(this.getField(pragma[only_bind_into](pos)))
}
/** Gets the tuple field that matches the `pos`th pattern of this pattern. */
pragma[nomagic]
TupleField getTupleField(int pos) {
exists(PathResolution::ItemNode i | i = this.getResolvedPath(pos) |
result.isStructField(i, pos) or
result.isVariantField(i, pos)
)
}
}
}

View File

@@ -15,7 +15,10 @@ module Impl {
/**
* A UseTree. For example:
* ```rust
* todo!()
* use std::collections::HashMap;
* use std::collections::*;
* use std::collections::HashMap as MyHashMap;
* use std::collections::{self, HashMap, HashSet};
* ```
*/
class UseTree extends Generated::UseTree { }

View File

@@ -1,6 +1,7 @@
private import rust
private import codeql.rust.controlflow.ControlFlowGraph
private import codeql.rust.elements.internal.generated.ParentChild
private import codeql.rust.elements.internal.PathImpl::Impl as PathImpl
private import codeql.rust.elements.internal.PathExprBaseImpl::Impl as PathExprBaseImpl
private import codeql.rust.elements.internal.FormatTemplateVariableAccessImpl::Impl as FormatTemplateVariableAccessImpl
private import codeql.util.DenseRank
@@ -172,16 +173,7 @@ module Impl {
string name_;
VariableAccessCand() {
exists(Path p, PathSegment ps |
p = this.(PathExpr).getPath() and
not p.hasQualifier() and
ps = p.getPart() and
not ps.hasGenericArgList() and
not ps.hasParenthesizedArgList() and
not ps.hasPathType() and
not ps.hasReturnTypeSyntax() and
name_ = ps.getNameRef().getText()
)
name_ = this.(PathExpr).getPath().(PathImpl::IdentPath).getName()
or
this.(FormatTemplateVariableAccess).getName() = name_
}
@@ -397,20 +389,23 @@ module Impl {
)
}
private newtype TVariableOrAccessCand =
TVariableOrAccessCandVariable(Variable v) or
TVariableOrAccessCandVariableAccessCand(VariableAccessCand va)
private newtype TDefOrAccessCand =
TDefOrAccessCandNestedFunction(Function f, BlockExprScope scope) {
f = scope.getStmtList().getAStatement()
} or
TDefOrAccessCandVariable(Variable v) or
TDefOrAccessCandVariableAccessCand(VariableAccessCand va)
/**
* A variable declaration or variable access candidate.
* A nested function declaration, variable declaration, or variable (or function)
* access candidate.
*
* In order to determine whether a candidate is an actual variable access,
* we rank declarations and candidates by their position in source code.
* In order to determine whether a candidate is an actual variable/function access,
* we rank declarations and candidates by their position in the AST.
*
* The ranking must take variable names into account, but also variable scopes;
* below a comment `rank(scope, name, i)` means that the declaration/access on
* the given line has rank `i` amongst all declarations/accesses inside variable
* scope `scope`, for variable name `name`:
* The ranking must take names into account, but also variable scopes; below a comment
* `rank(scope, name, i)` means that the declaration/access on the given line has rank
* `i` amongst all declarations/accesses inside variable scope `scope`, for name `name`:
*
* ```rust
* fn f() { // scope0
@@ -430,8 +425,8 @@ module Impl {
* }
* ```
*
* Variable declarations are only ranked in the scope that they bind into, while
* accesses candidates propagate outwards through scopes, as they may access
* Function/variable declarations are only ranked in the scope that they bind into,
* while accesses candidates propagate outwards through scopes, as they may access
* declarations from outer scopes.
*
* For an access candidate with ranks `{ rank(scope_i, name, rnk_i) | i in I }` and
@@ -448,41 +443,80 @@ module Impl {
* i.e., its the nearest declaration before the access in the same (or outer) scope
* as the access.
*/
private class VariableOrAccessCand extends TVariableOrAccessCand {
Variable asVariable() { this = TVariableOrAccessCandVariable(result) }
abstract private class DefOrAccessCand extends TDefOrAccessCand {
abstract string toString();
VariableAccessCand asVariableAccessCand() {
this = TVariableOrAccessCandVariableAccessCand(result)
}
string toString() {
result = this.asVariable().toString() or result = this.asVariableAccessCand().toString()
}
Location getLocation() {
result = this.asVariable().getLocation() or result = this.asVariableAccessCand().getLocation()
}
abstract Location getLocation();
pragma[nomagic]
predicate rankBy(string name, VariableScope scope, int ord, int kind) {
variableDeclInScope(this.asVariable(), scope, name, ord) and
abstract predicate rankBy(string name, VariableScope scope, int ord, int kind);
}
abstract private class NestedFunctionOrVariable extends DefOrAccessCand { }
private class DefOrAccessCandNestedFunction extends NestedFunctionOrVariable,
TDefOrAccessCandNestedFunction
{
private Function f;
private BlockExprScope scope_;
DefOrAccessCandNestedFunction() { this = TDefOrAccessCandNestedFunction(f, scope_) }
override string toString() { result = f.toString() }
override Location getLocation() { result = f.getLocation() }
override predicate rankBy(string name, VariableScope scope, int ord, int kind) {
// nested functions behave as if they are defined at the beginning of the scope
name = f.getName().getText() and
scope = scope_ and
ord = 0 and
kind = 0
or
variableAccessCandInScope(this.asVariableAccessCand(), scope, name, _, ord) and
}
}
private class DefOrAccessCandVariable extends NestedFunctionOrVariable, TDefOrAccessCandVariable {
private Variable v;
DefOrAccessCandVariable() { this = TDefOrAccessCandVariable(v) }
override string toString() { result = v.toString() }
override Location getLocation() { result = v.getLocation() }
override predicate rankBy(string name, VariableScope scope, int ord, int kind) {
variableDeclInScope(v, scope, name, ord) and
kind = 1
}
}
private class DefOrAccessCandVariableAccessCand extends DefOrAccessCand,
TDefOrAccessCandVariableAccessCand
{
private VariableAccessCand va;
DefOrAccessCandVariableAccessCand() { this = TDefOrAccessCandVariableAccessCand(va) }
override string toString() { result = va.toString() }
override Location getLocation() { result = va.getLocation() }
override predicate rankBy(string name, VariableScope scope, int ord, int kind) {
variableAccessCandInScope(va, scope, name, _, ord) and
kind = 2
}
}
private module DenseRankInput implements DenseRankInputSig2 {
class C1 = VariableScope;
class C2 = string;
class Ranked = VariableOrAccessCand;
class Ranked = DefOrAccessCand;
int getRank(VariableScope scope, string name, VariableOrAccessCand v) {
int getRank(VariableScope scope, string name, DefOrAccessCand v) {
v =
rank[result](VariableOrAccessCand v0, int ord, int kind |
rank[result](DefOrAccessCand v0, int ord, int kind |
v0.rankBy(name, scope, ord, kind)
|
v0 order by ord, kind
@@ -494,7 +528,7 @@ module Impl {
* Gets the rank of `v` amongst all other declarations or access candidates
* to a variable named `name` in the variable scope `scope`.
*/
private int rankVariableOrAccess(VariableScope scope, string name, VariableOrAccessCand v) {
private int rankVariableOrAccess(VariableScope scope, string name, DefOrAccessCand v) {
v = DenseRank2<DenseRankInput>::denseRank(scope, name, result + 1)
}
@@ -512,25 +546,38 @@ module Impl {
* the declaration at rank 0 can only reach the access at rank 1, while the declaration
* at rank 2 can only reach the access at rank 3.
*/
private predicate variableReachesRank(VariableScope scope, string name, Variable v, int rnk) {
rnk = rankVariableOrAccess(scope, name, TVariableOrAccessCandVariable(v))
private predicate variableReachesRank(
VariableScope scope, string name, NestedFunctionOrVariable v, int rnk
) {
rnk = rankVariableOrAccess(scope, name, v)
or
variableReachesRank(scope, name, v, rnk - 1) and
rnk = rankVariableOrAccess(scope, name, TVariableOrAccessCandVariableAccessCand(_))
rnk = rankVariableOrAccess(scope, name, TDefOrAccessCandVariableAccessCand(_))
}
private predicate variableReachesCand(
VariableScope scope, string name, Variable v, VariableAccessCand cand, int nestLevel
VariableScope scope, string name, NestedFunctionOrVariable v, VariableAccessCand cand,
int nestLevel
) {
exists(int rnk |
variableReachesRank(scope, name, v, rnk) and
rnk = rankVariableOrAccess(scope, name, TVariableOrAccessCandVariableAccessCand(cand)) and
rnk = rankVariableOrAccess(scope, name, TDefOrAccessCandVariableAccessCand(cand)) and
variableAccessCandInScope(cand, scope, name, nestLevel, _)
)
}
pragma[nomagic]
predicate access(string name, NestedFunctionOrVariable v, VariableAccessCand cand) {
v =
min(NestedFunctionOrVariable v0, int nestLevel |
variableReachesCand(_, name, v0, cand, nestLevel)
|
v0 order by nestLevel
)
}
/** A variable access. */
class VariableAccess extends PathExprBaseImpl::PathExprBase instanceof VariableAccessCand {
class VariableAccess extends PathExprBaseImpl::PathExprBase {
private string name;
private Variable v;
@@ -574,6 +621,16 @@ module Impl {
}
}
/** A nested function access. */
class NestedFunctionAccess extends PathExprBaseImpl::PathExprBase {
private Function f;
NestedFunctionAccess() { nestedFunctionAccess(_, f, this) }
/** Gets the function being accessed. */
Function getFunction() { result = f }
}
cached
private module Cached {
cached
@@ -582,12 +639,12 @@ module Impl {
cached
predicate variableAccess(string name, Variable v, VariableAccessCand cand) {
v =
min(Variable v0, int nestLevel |
variableReachesCand(_, name, v0, cand, nestLevel)
|
v0 order by nestLevel
)
access(name, TDefOrAccessCandVariable(v), cand)
}
cached
predicate nestedFunctionAccess(string name, Function f, VariableAccessCand cand) {
access(name, TDefOrAccessCandNestedFunction(f, _), cand)
}
}

View File

@@ -4,6 +4,7 @@
* INTERNAL: Do not use.
*/
private import rust
private import codeql.rust.elements.internal.generated.Variant
/**
@@ -20,5 +21,16 @@ module Impl {
*/
class Variant extends Generated::Variant {
override string toString() { result = this.getName().getText() }
/** Gets the record field named `name`, if any. */
pragma[nomagic]
RecordField getRecordField(string name) {
result = this.getFieldList().(RecordFieldList).getAField() and
result.getName().getText() = name
}
/** Gets the `i`th tuple field, if any. */
pragma[nomagic]
TupleField getTupleField(int i) { result = this.getFieldList().(TupleFieldList).getField(i) }
}
}

View File

@@ -10,6 +10,8 @@ import codeql.rust.elements.internal.AstNodeImpl::Impl as AstNodeImpl
import codeql.rust.elements.Path
import codeql.rust.elements.PathSegment
private class PathAlias = Path;
/**
* INTERNAL: This module contains the fully generated definition of `Path` and should not
* be referenced directly.
@@ -30,7 +32,7 @@ module Generated {
/**
* Gets the qualifier of this path, if it exists.
*/
Path getQualifier() {
PathAlias getQualifier() {
result = Synth::convertPathFromRaw(Synth::convertPathToRaw(this).(Raw::Path).getQualifier())
}

View File

@@ -1090,12 +1090,20 @@ module Raw {
* INTERNAL: Do not use.
* A UseTree. For example:
* ```rust
* todo!()
* use std::collections::HashMap;
* use std::collections::*;
* use std::collections::HashMap as MyHashMap;
* use std::collections::{self, HashMap, HashSet};
* ```
*/
class UseTree extends @use_tree, AstNode {
override string toString() { result = "UseTree" }
/**
* Holds if this use tree is glob.
*/
predicate isGlob() { use_tree_is_glob(this) }
/**
* Gets the path of this use tree, if it exists.
*/

View File

@@ -19,7 +19,10 @@ module Generated {
/**
* A UseTree. For example:
* ```rust
* todo!()
* use std::collections::HashMap;
* use std::collections::*;
* use std::collections::HashMap as MyHashMap;
* use std::collections::{self, HashMap, HashSet};
* ```
* INTERNAL: Do not reference the `Generated::UseTree` class directly.
* Use the subclass `UseTree`, where the following predicates are available.
@@ -27,6 +30,11 @@ module Generated {
class UseTree extends Synth::TUseTree, AstNodeImpl::AstNode {
override string getAPrimaryQlClass() { result = "UseTree" }
/**
* Holds if this use tree is glob.
*/
predicate isGlob() { Synth::convertUseTreeToRaw(this).(Raw::UseTree).isGlob() }
/**
* Gets the path of this use tree, if it exists.
*/

View File

@@ -0,0 +1,17 @@
extensions:
- addsTo:
pack: codeql/rust-all
extensible: sinkModel
data:
- ["repo:https://github.com/rust-lang/log:log", "crate::__private_api::log", "Argument[0]", "log-injection", "manual"] # args
- ["repo:https://github.com/rust-lang/log:log", "crate::__private_api::log", "Argument[2]", "log-injection", "manual"] # target
- ["repo:https://github.com/rust-lang/log:log", "crate::__private_api::log", "Argument[3]", "log-injection", "manual"] # key value
- ["lang:std", "crate::io::stdio::_print", "Argument[0]", "log-injection", "manual"]
- ["lang:std", "crate::io::stdio::_eprint", "Argument[0]", "log-injection", "manual"]
- ["lang:std", "<crate::io::stdio::StdoutLock as crate::io::Write>::write", "Argument[0]", "log-injection", "manual"]
- ["lang:std", "<crate::io::stdio::StdoutLock as crate::io::Write>::write_all", "Argument[0]", "log-injection", "manual"]
- ["lang:std", "<crate::io::stdio::StderrLock as crate::io::Write>::write", "Argument[0]", "log-injection", "manual"]
- ["lang:std", "<crate::io::stdio::StderrLock as crate::io::Write>::write_all", "Argument[0]", "log-injection", "manual"]
- ["lang:core", "crate::panicking::panic_fmt", "Argument[0]", "log-injection", "manual"]
- ["lang:core", "crate::panicking::assert_failed", "Argument[3].Variant[crate::option::Option::Some(0)]", "log-injection", "manual"]
- ["lang:core", "<crate::option::Option>::expect", "Argument[0]", "log-injection", "manual"]

View File

@@ -3,10 +3,16 @@ extensions:
pack: codeql/rust-all
extensible: sourceModel
data:
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::get", "ReturnValue", "remote", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::blocking::get", "ReturnValue", "remote", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::get", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "remote", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "crate::blocking::get", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "remote", "manual"]
- addsTo:
pack: codeql/rust-all
extensible: summaryModel
data:
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::text", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::text_with_charset", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::bytes", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::response::Response>::chunk", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)].Variant[crate::option::Option::Some(0)]", "taint", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::blocking::response::Response>::text", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::blocking::response::Response>::text_with_charset", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"]
- ["repo:https://github.com/seanmonstar/reqwest:reqwest", "<crate::blocking::response::Response>::bytes", "Argument[self]", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "taint", "manual"]

View File

@@ -25,10 +25,9 @@ class StreamCipherInit extends Cryptography::CryptographicOperation::Range {
exists(PathExpr p, string rawAlgorithmName |
this.asExpr().getExpr().(CallExpr).getFunction() = p and
p.getResolvedCrateOrigin().matches("%/RustCrypto%") and
p.getPath().getPart().getNameRef().getText() =
["new", "new_from_slice", "new_from_slices", "new_with_eff_key_len"] and
p.getPath().getText() = ["new", "new_from_slice", "new_from_slices", "new_with_eff_key_len"] and
(
rawAlgorithmName = p.getPath().getQualifier().getPart().getNameRef().getText() or
rawAlgorithmName = p.getPath().getQualifier().getText() or
rawAlgorithmName =
p.getPath()
.getQualifier()

View File

@@ -0,0 +1,21 @@
/** A model for `clone` on the `Clone` trait. */
private import rust
private import codeql.rust.dataflow.FlowSummary
/** A `clone` method. */
final class CloneCallable extends SummarizedCallable::Range {
CloneCallable() {
// NOTE: The function target may not exist in the database, so we base this
// on method calls.
exists(MethodCallExpr c |
c.getNameRef().getText() = "clone" and
c.getArgList().getNumberOfArgs() = 0 and
this = c.getResolvedCrateOrigin() + "::_::" + c.getResolvedPath()
)
}
final override predicate propagatesFlow(string input, string output, boolean preservesValue) {
input = "Argument[self]" and output = "ReturnValue" and preservesValue = true
}
}

View File

@@ -5,10 +5,10 @@ extensions:
data:
- ["lang:std", "crate::env::args", "ReturnValue", "command-line-source", "manual"]
- ["lang:std", "crate::env::args_os", "ReturnValue", "command-line-source", "manual"]
- ["lang:std", "crate::env::current_dir", "ReturnValue", "command-line-source", "manual"]
- ["lang:std", "crate::env::current_exe", "ReturnValue", "command-line-source", "manual"]
- ["lang:std", "crate::env::home_dir", "ReturnValue", "command-line-source", "manual"]
- ["lang:std", "crate::env::var", "ReturnValue", "environment-source", "manual"]
- ["lang:std", "crate::env::var_os", "ReturnValue", "environment-source", "manual"]
- ["lang:std", "crate::env::current_dir", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "command-line-source", "manual"]
- ["lang:std", "crate::env::current_exe", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "command-line-source", "manual"]
- ["lang:std", "crate::env::home_dir", "ReturnValue.Variant[crate::option::Option::Some(0)]", "command-line-source", "manual"]
- ["lang:std", "crate::env::var", "ReturnValue.Variant[crate::result::Result::Ok(0)]", "environment-source", "manual"]
- ["lang:std", "crate::env::var_os", "ReturnValue.Variant[crate::option::Option::Some(0)]", "environment-source", "manual"]
- ["lang:std", "crate::env::vars", "ReturnValue", "environment-source", "manual"]
- ["lang:std", "crate::env::vars_os", "ReturnValue", "environment-source", "manual"]

View File

@@ -3,17 +3,31 @@ extensions:
pack: codeql/rust-all
extensible: summaryModel
data:
# Fmt
- ["lang:alloc", "crate::fmt::format", "Argument[0]", "ReturnValue", "taint", "manual"]
# Hint
- ["lang:core", "crate::hint::must_use", "Argument[0]", "ReturnValue", "value", "manual"]
# Option
- ["lang:core", "<crate::option::Option>::unwrap", "Argument[self].Variant[crate::option::Option::Some(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::option::Option>::unwrap_or", "Argument[self].Variant[crate::option::Option::Some(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::option::Option>::unwrap_or", "Argument[0]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::option::Option>::unwrap_or_default", "Argument[self].Variant[crate::option::Option::Some(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::option::Option>::unwrap_or_else", "Argument[self].Variant[crate::option::Option::Some(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::option::Option>::unwrap_or_else", "Argument[0].ReturnValue", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::option::Option>::unwrap_unchecked", "Argument[self].Variant[crate::option::Option::Some(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::option::Option>::expect", "Argument[self].Variant[crate::option::Option::Some(0)]", "ReturnValue", "value", "manual"]
# Result
- ["lang:core", "<crate::result::Result>::unwrap", "Argument[self].Variant[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_or", "Argument[self].Variant[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_or", "Argument[0]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_or_default", "Argument[self].Variant[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_or_else", "Argument[self].Variant[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_or_else", "Argument[0].ReturnValue", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_unchecked", "Argument[self].Variant[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_err", "Argument[self].Variant[crate::result::Result::Err(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::unwrap_err_unchecked", "Argument[self].Variant[crate::result::Result::Err(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::expect", "Argument[self].Variant[crate::result::Result::Ok(0)]", "ReturnValue", "value", "manual"]
- ["lang:core", "<crate::result::Result>::expect_err", "Argument[self].Variant[crate::result::Result::Err(0)]", "ReturnValue", "value", "manual"]
# String
- ["lang:alloc", "<crate::string::String>::as_str", "Argument[self]", "ReturnValue", "taint", "manual"]
# Hint
- ["lang:core", "crate::hint::must_use", "Argument[0]", "ReturnValue", "value", "manual"]
# Fmt
- ["lang:alloc", "crate::fmt::format", "Argument[0]", "ReturnValue", "taint", "manual"]
- ["lang:alloc", "<crate::string::String>::as_bytes", "Argument[self]", "ReturnValue", "taint", "manual"]

View File

@@ -0,0 +1,40 @@
/**
* Provides classes and predicates for reasoning about cleartext logging
* of sensitive information vulnerabilities.
*/
import rust
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.security.SensitiveData
/**
* Provides default sources, sinks and barriers for detecting cleartext logging
* vulnerabilities, as well as extension points for adding your own.
*/
module CleartextLogging {
/**
* A data flow source for cleartext logging vulnerabilities.
*/
abstract class Source extends DataFlow::Node { }
/**
* A data flow sink for cleartext logging vulnerabilities.
*/
abstract class Sink extends DataFlow::Node { }
/**
* A barrier for cleartext logging vulnerabilities.
*/
abstract class Barrier extends DataFlow::Node { }
/**
* Sensitive data, considered as a flow source.
*/
private class SensitiveDataAsSource extends Source instanceof SensitiveData { }
/** A sink for logging from model data. */
private class ModelsAsDataSinks extends Sink {
ModelsAsDataSinks() { exists(string s | sinkNode(this, s) and s.matches("log-injection%")) }
}
}

View File

@@ -186,8 +186,7 @@ class ModeledHashOperation extends Cryptography::CryptographicOperation::Range {
sinkNode(input, "hasher-input") and
call = input.(Node::FlowSummaryNode).getSinkElement().getCall() and
call = this.asExpr().getExpr() and
algorithmName =
call.getFunction().(PathExpr).getPath().getQualifier().getPart().getNameRef().getText()
algorithmName = call.getFunction().(PathExpr).getPath().getQualifier().getText()
)
}

View File

@@ -1,5 +1,5 @@
name: codeql/rust-all
version: 0.1.1-dev
version: 0.1.2-dev
groups: rust
extractor: rust
dbscheme: rust.dbscheme

View File

@@ -1094,6 +1094,11 @@ use_trees(
unique int id: @use_tree
);
#keyset[id]
use_tree_is_glob(
int id: @use_tree ref
);
#keyset[id]
use_tree_paths(
int id: @use_tree ref,

View File

@@ -0,0 +1,21 @@
private import rust as R
private import codeql.mad.test.InlineMadTest
private module InlineMadTestLang implements InlineMadTestLangSig {
class Callable = R::Function;
string getComment(R::Function callable) {
exists(R::Comment comment |
result = comment.getCommentText() and
comment.getLocation().getFile() = callable.getLocation().getFile() and
// When a function is preceded by comments its start line is the line of
// the first comment. Hence all relevant comments are found by including
// comments from the start line and up to the line with the function
// name.
callable.getLocation().getStartLine() <= comment.getLocation().getStartLine() and
comment.getLocation().getStartLine() <= callable.getName().getLocation().getStartLine()
)
}
}
import InlineMadTestImpl<InlineMadTestLang>

View File

@@ -0,0 +1,9 @@
private import codeql.dataflow.test.ProvenancePathGraph as Graph
private import codeql.rust.dataflow.internal.ModelsAsData as MaD
private signature predicate provenanceSig(string model);
/** Translates models-as-data provenance information into a format that can be used in tests. */
module TranslateModels<provenanceSig/1 provenance> {
import Graph::TranslateModels<MaD::interpretModelForTest/2, provenance/1>
}

View File

@@ -1,3 +1,7 @@
## 0.1.1
No user-facing changes.
## 0.1.0
No user-facing changes.

View File

@@ -0,0 +1,3 @@
## 0.1.1
No user-facing changes.

View File

@@ -1,2 +1,2 @@
---
lastReleaseVersion: 0.1.0
lastReleaseVersion: 0.1.1

View File

@@ -0,0 +1 @@
[]

View File

@@ -1,5 +1,5 @@
name: codeql/rust-queries
version: 0.1.1-dev
version: 0.1.2-dev
groups:
- rust
- queries

View File

@@ -0,0 +1,38 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
Sensitive user data and system information that is logged could be exposed to an attacker when it is
displayed. Also, external processes often store the standard output and standard error streams of
an application, which will include logged sensitive information.
</p>
</overview>
<recommendation>
<p>
Do not log sensitive data. If it is necessary to log sensitive data, encrypt it before logging.
</p>
</recommendation>
<example>
<p>
The following example code logs user credentials (in this case, their password) in plaintext:
</p>
<sample src="CleartextLoggingBad.rs"/>
<p>
Instead, you should encrypt the credentials, or better still, omit them entirely:
</p>
<sample src="CleartextLoggingGood.rs"/>
</example>
<references>
<li>M. Dowd, J. McDonald and J. Schuhm, <i>The Art of Software Security Assessment</i>, 1st Edition, Chapter 2 - 'Common Vulnerabilities of Encryption', p. 43. Addison Wesley, 2006.</li>
<li>M. Howard and D. LeBlanc, <i>Writing Secure Code</i>, 2nd Edition, Chapter 9 - 'Protecting Secret Data', p. 299. Microsoft, 2002.</li>
<li>OWASP: <a href="https://cheatsheetseries.owasp.org/cheatsheets/Logging_Cheat_Sheet.html#data-to-exclude">Logging Cheat Sheet - Data to exclude</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,58 @@
/**
* @name Cleartext logging of sensitive information
* @description Logging sensitive information in plaintext can
* expose it to an attacker.
* @kind path-problem
* @problem.severity error
* @security-severity 7.5
* @precision high
* @id rust/cleartext-logging
* @tags security
* external/cwe/cwe-312
* external/cwe/cwe-359
* external/cwe/cwe-532
*/
import rust
import codeql.rust.security.CleartextLoggingExtensions
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.TaintTracking
import codeql.rust.dataflow.internal.DataFlowImpl
/**
* A taint-tracking configuration for cleartext logging vulnerabilities.
*/
module CleartextLoggingConfig implements DataFlow::ConfigSig {
import CleartextLogging
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node barrier) { barrier instanceof Barrier }
predicate isBarrierIn(DataFlow::Node node) {
// make sources barriers so that we only report the closest instance
isSource(node)
}
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
// flow from `a` to `&a`
node2.asExpr().getExpr().(RefExpr).getExpr() = node1.asExpr().getExpr()
}
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
// flow out from tuple content at sinks.
isSink(node) and
c.getAReadContent() instanceof TuplePositionContent
}
}
module CleartextLoggingFlow = TaintTracking::Global<CleartextLoggingConfig>;
import CleartextLoggingFlow::PathGraph
from CleartextLoggingFlow::PathNode source, CleartextLoggingFlow::PathNode sink
where CleartextLoggingFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This operation writes $@ to a log file.", source,
source.getNode().toString()

View File

@@ -0,0 +1,2 @@
let password = "P@ssw0rd";
info!("User password changed to {password}");

View File

@@ -0,0 +1,2 @@
let password = "P@ssw0rd";
info!("User password changed");

View File

@@ -20,7 +20,7 @@ class CtorAttr extends Attr {
string whichAttr;
CtorAttr() {
whichAttr = this.getMeta().getPath().getPart().getNameRef().getText() and
whichAttr = this.getMeta().getPath().getText() and
whichAttr = ["ctor", "dtor"]
}

View File

@@ -10,6 +10,7 @@ private import codeql.rust.AstConsistency as AstConsistency
private import codeql.rust.controlflow.internal.CfgConsistency as CfgConsistency
private import codeql.rust.dataflow.internal.DataFlowConsistency as DataFlowConsistency
private import codeql.rust.security.SqlInjectionExtensions
private import codeql.rust.security.CleartextLoggingExtensions
/**
* Gets a count of the total number of lines of code in the database.
@@ -58,7 +59,9 @@ int getTaintEdgesCount() {
* Gets a kind of query for which `n` is a sink (if any).
*/
string getAQuerySinkKind(DataFlow::Node n) {
(n instanceof SqlInjection::Sink and result = "SqlInjection")
n instanceof SqlInjection::Sink and result = "SqlInjection"
or
n instanceof CleartextLogging::Sink and result = "CleartextLogging"
}
/**

View File

@@ -0,0 +1,13 @@
/**
* @name Capture content based summary models.
* @description Finds applicable content based summary models to be used by other queries.
* @kind diagnostic
* @id rust/utils/modelgenerator/contentbased-summary-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string flow
where flow = ContentSensitive::captureFlow(api, _)
select flow order by flow

View File

@@ -0,0 +1,13 @@
/**
* @name Capture mixed neutral models.
* @description Finds neutral models to be used by other queries.
* @kind diagnostic
* @id rust/utils/modelgenerator/mixed-neutral-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string noflow
where noflow = captureMixedNeutral(api)
select noflow order by noflow

View File

@@ -0,0 +1,13 @@
/**
* @name Capture mixed summary models.
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id rust/utils/modelgenerator/mixed-summary-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string flow
where flow = captureMixedFlow(api, _)
select flow order by flow

View File

@@ -0,0 +1,13 @@
/**
* @name Capture neutral models.
* @description Finds neutral models to be used by other queries.
* @kind diagnostic
* @id rust/utils/modelgenerator/neutral-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string noflow
where noflow = captureNoFlow(api)
select noflow order by noflow

View File

@@ -0,0 +1,13 @@
/**
* @name Capture sink models.
* @description Finds public methods that act as sinks as they flow into a known sink.
* @kind diagnostic
* @id rust/utils/modelgenerator/sink-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSinkTargetApi api, string sink
where sink = captureSink(api)
select sink order by sink

View File

@@ -0,0 +1,13 @@
/**
* @name Capture source models.
* @description Finds APIs that act as sources as they expose already known sources.
* @kind diagnostic
* @id rust/utils/modelgenerator/source-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSourceTargetApi api, string source
where source = captureSource(api)
select source order by source

View File

@@ -0,0 +1,13 @@
/**
* @name Capture summary models.
* @description Finds applicable summary models to be used by other queries.
* @kind diagnostic
* @id rust/utils/modelgenerator/summary-models
* @tags modelgenerator
*/
import internal.CaptureModels
from DataFlowSummaryTargetApi api, string flow
where flow = captureFlow(api)
select flow order by flow

View File

@@ -0,0 +1,15 @@
#!/usr/bin/python3
import sys
import os.path
import subprocess
# Add Model as Data script directory to sys.path.
gitroot = subprocess.check_output(["git", "rev-parse", "--show-toplevel"]).decode("utf-8").strip()
madpath = os.path.join(gitroot, "misc/scripts/models-as-data/")
sys.path.append(madpath)
import generate_flow_model as model
language = "rust"
model.Generator.make(language).run()

View File

@@ -0,0 +1,27 @@
/**
* @name Capture Summary Models Partial Path
* @description Capture Summary Models Partial Path
* @kind path-problem
* @precision low
* @id rust/utils/modelgenerator/summary-models-partial-path
* @severity info
* @tags modelgenerator
*/
private import codeql.rust.dataflow.DataFlow
import utils.modelgenerator.internal.CaptureModels
import PartialFlow::PartialPathGraph
int explorationLimit() { result = 3 }
module PartialFlow = PropagateFlow::FlowExplorationFwd<explorationLimit/0>;
from
PartialFlow::PartialPathNode source, PartialFlow::PartialPathNode sink,
DataFlowSummaryTargetApi api, DataFlow::ParameterNode p
where
PartialFlow::partialFlow(source, sink, _) and
p = source.getNode() and
p.asParameter() = api.getParamList().getAParamBase()
select sink.getNode(), source, sink, "There is flow from a $@ to $@.", source.getNode(),
"parameter", sink.getNode(), "intermediate value"

View File

@@ -0,0 +1,24 @@
/**
* @name Capture Summary Models Path
* @description Capture Summary Models Path
* @kind path-problem
* @precision low
* @id rust/utils/modelgenerator/summary-models-path
* @severity warning
* @tags modelgenerator
*/
private import codeql.rust.dataflow.DataFlow
import utils.modelgenerator.internal.CaptureModels
import PropagateFlow::PathGraph
from
PropagateFlow::PathNode source, PropagateFlow::PathNode sink, DataFlowSummaryTargetApi api,
DataFlow::Node p, DataFlow::Node returnNodeExt
where
PropagateFlow::flowPath(source, sink) and
p = source.getNode() and
returnNodeExt = sink.getNode() and
exists(captureThroughFlow0(api, p, returnNodeExt))
select sink.getNode(), source, sink, "There is flow from $@ to the $@.", source.getNode(),
"parameter", sink.getNode(), "return value"

View File

@@ -0,0 +1 @@
The queries in this directory are purely used for model generator debugging purposes in VS Code.

View File

@@ -0,0 +1,185 @@
private import codeql.util.Unit
private import rust
private import rust as R
private import codeql.rust.dataflow.DataFlow
private import codeql.rust.dataflow.internal.DataFlowImpl
private import codeql.rust.dataflow.internal.TaintTrackingImpl
private import codeql.mad.modelgenerator.internal.ModelGeneratorImpl
private import codeql.rust.dataflow.internal.FlowSummaryImpl as FlowSummary
module ModelGeneratorInput implements ModelGeneratorInputSig<Location, RustDataFlow> {
// NOTE: We are not using type information for now.
class Type = Unit;
class Parameter = R::ParamBase;
class Callable = R::Callable;
class NodeExtended extends DataFlow::Node {
Callable getAsExprEnclosingCallable() { result = this.asExpr().getScope() }
Type getType() { any() }
Callable getEnclosingCallable() {
result = this.(Node::Node).getEnclosingCallable().asCfgScope()
}
}
private predicate relevant(Function api) {
// This excludes closures (these are not exported API endpoints) and
// functions without a `pub` visiblity. A function can be `pub` without
// ultimately being exported by a crate, so this is an overapproximation.
api.hasVisibility()
or
// If a method implements a public trait it is exposed through the trait.
// We overapproximate this by including all trait method implementations.
exists(Impl impl | impl.hasTrait() and impl.getAssocItemList().getAssocItem(_) = api)
}
predicate isUninterestingForDataFlowModels(Callable api) { none() }
predicate isUninterestingForHeuristicDataFlowModels(Callable api) { none() }
class SourceOrSinkTargetApi extends Callable {
SourceOrSinkTargetApi() { relevant(this) }
}
class SinkTargetApi extends SourceOrSinkTargetApi { }
class SourceTargetApi extends SourceOrSinkTargetApi { }
class SummaryTargetApi extends Callable {
private Callable lift;
SummaryTargetApi() {
lift = this and
relevant(this)
}
Callable lift() { result = lift }
predicate isRelevant() { relevant(this) }
}
predicate isRelevantType(Type t) { any() }
/**
* Gets the underlying type of the content `c`.
*/
Type getUnderlyingContentType(DataFlow::ContentSet c) { result = any(Type t) and exists(c) }
string qualifierString() { result = "Argument[self]" }
string parameterAccess(R::ParamBase p) {
result = "Argument[" + any(ParameterPosition pos | p = pos.getParameterIn(_)).toString() + "]"
}
string parameterContentAccess(R::ParamBase p) { result = parameterAccess(p) }
class InstanceParameterNode extends DataFlow::ParameterNode {
InstanceParameterNode() { this.asParameter() instanceof SelfParam }
}
bindingset[c]
string paramReturnNodeAsOutput(R::Callable c, ParameterPosition pos) {
// TODO: Implement this to support returning through parameters.
result = "paramReturnNodeAsOutput(" + c + ", " + pos + ")"
}
bindingset[c]
string paramReturnNodeAsContentOutput(Callable c, ParameterPosition pos) {
result = parameterContentAccess(c.getParamList().getParam(pos.getPosition()))
or
pos.isSelf() and result = qualifierString()
}
Callable returnNodeEnclosingCallable(DataFlow::Node ret) {
result = ret.(Node::Node).getEnclosingCallable().asCfgScope()
}
predicate isOwnInstanceAccessNode(RustDataFlow::ReturnNode node) {
// This is probably not relevant to implement for Rust, as we only use
// `captureMixedFlow` which doesn't explicitly distinguish between
// functions that return `self` and those that don't.
none()
}
predicate sinkModelSanitizer(DataFlow::Node node) { none() }
predicate apiSource(DataFlow::Node source) { none() }
bindingset[sourceEnclosing, api]
predicate irrelevantSourceSinkApi(Callable sourceEnclosing, SourceTargetApi api) { none() }
string getInputArgument(DataFlow::Node source) {
// TODO: Implement when we want to generate sources and sinks
result = "getInputArgument(" + source + ")"
}
bindingset[kind]
predicate isRelevantSinkKind(string kind) { any() }
bindingset[kind]
predicate isRelevantSourceKind(string kind) { any() }
predicate containerContent(DataFlow::ContentSet c) {
c.(SingletonContentSet).getContent() instanceof ElementContent
}
predicate isAdditionalContentFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) { none() }
predicate isField(DataFlow::ContentSet c) {
c.(SingletonContentSet).getContent() instanceof FieldContent
}
predicate isCallback(DataFlow::ContentSet cs) {
exists(Content c | c = cs.(SingletonContentSet).getContent() |
c instanceof FunctionCallReturnContent or
c instanceof FunctionCallArgumentContent
)
}
string getSyntheticName(DataFlow::ContentSet c) { none() }
private string encodeContent(ContentSet cs, string arg) {
result = FlowSummary::Input::encodeContent(cs, arg)
or
exists(Content c | cs = TSingletonContentSet(c) |
exists(int pos |
pos = c.(FunctionCallArgumentContent).getPosition() and
result = "Parameter" and
arg = pos.toString()
)
or
c instanceof FunctionCallReturnContent and result = "ReturnValue" and arg = ""
)
}
string printContent(DataFlow::ContentSet cs) {
exists(string name, string arg |
name = encodeContent(cs, arg) and
if arg = "" then result = name else result = name + "[" + arg + "]"
)
}
string partialModelRow(Callable api, int i) {
i = 0 and
(
result = api.(Function).getCrateOrigin()
or
not api.(Function).hasCrateOrigin() and result = ""
) // crate
or
i = 1 and result = api.(Function).getExtendedCanonicalPath() // name
}
string partialNeutralModelRow(Callable api, int i) { result = partialModelRow(api, i) }
// TODO: Implement this when we want to generate sources.
predicate sourceNode(DataFlow::Node node, string kind) { none() }
// TODO: Implement this when we want to generate sinks.
predicate sinkNode(DataFlow::Node node, string kind) { none() }
}
import MakeModelGenerator<Location, RustDataFlow, RustTaintTracking, ModelGeneratorInput>

View File

@@ -0,0 +1,13 @@
private import rust as R
private import codeql.mad.modelgenerator.internal.ModelPrinting
private import CaptureModels::ModelGeneratorInput as ModelGeneratorInput
private module ModelPrintingLang implements ModelPrintingLangSig {
class Callable = R::Callable;
predicate partialModelRow = ModelGeneratorInput::partialModelRow/2;
predicate partialNeutralModelRow = ModelGeneratorInput::partialNeutralModelRow/2;
}
import ModelPrintingImpl<ModelPrintingLang>

View File

@@ -130,7 +130,7 @@ TypeParam/gen_type_param.rs 31c02d18020b305f1c37fdeb97656dd5b1e49e6b9a072329c2f0
UnderscoreExpr/gen_underscore_expr.rs fe34e99d322bf86c0f5509c9b5fd6e1e8abbdf63dbe7e01687344a41e9aabe52 fe34e99d322bf86c0f5509c9b5fd6e1e8abbdf63dbe7e01687344a41e9aabe52
Union/gen_union.rs d5e814688e93dcb105f29a392159c1b995ee15a74720167219f9431db8ef70a3 d5e814688e93dcb105f29a392159c1b995ee15a74720167219f9431db8ef70a3
Use/gen_use.rs 2a0ea9fa34d844fda63e8f605f6a951e8b272d63ebfb0ae501fc734559a83a6b 2a0ea9fa34d844fda63e8f605f6a951e8b272d63ebfb0ae501fc734559a83a6b
UseTree/gen_use_tree.rs 0a310eb8ce7abf481df813464dabac528a8f70d64d541409c66f957dfdd068d0 0a310eb8ce7abf481df813464dabac528a8f70d64d541409c66f957dfdd068d0
UseTree/gen_use_tree.rs bf7525e8641a5a90a7e07214e7480b6507737cf60f9bd4d8b82bc71a8b9d7e8d bf7525e8641a5a90a7e07214e7480b6507737cf60f9bd4d8b82bc71a8b9d7e8d
UseTreeList/gen_use_tree_list.rs ba450699782e51b1d3139148709827e35f2e57235849fb26a073e2786dfc53e3 ba450699782e51b1d3139148709827e35f2e57235849fb26a073e2786dfc53e3
Variant/gen_variant.rs 036566793ee468418f915974e2925d8bafaec3c93c2463212f222e6a5f290f24 036566793ee468418f915974e2925d8bafaec3c93c2463212f222e6a5f290f24
VariantList/gen_variant_list.rs 932b67564c5ef4116d84db6945e098f6d7438755d99fc198fde8f4527979bf00 932b67564c5ef4116d84db6945e098f6d7438755d99fc198fde8f4527979bf00

View File

@@ -1,2 +1,2 @@
| gen_record_pat_field.rs:5:15:5:18 | RecordPatField | getNumberOfAttrs: | 0 | hasNameRef: | yes | hasPat: | yes |
| gen_record_pat_field.rs:5:21:5:24 | RecordPatField | getNumberOfAttrs: | 0 | hasNameRef: | yes | hasPat: | yes |
| gen_record_pat_field.rs:5:15:5:18 | a: 1 | getNumberOfAttrs: | 0 | hasNameRef: | yes | hasPat: | yes |
| gen_record_pat_field.rs:5:21:5:24 | b: 2 | getNumberOfAttrs: | 0 | hasNameRef: | yes | hasPat: | yes |

View File

@@ -1,2 +1,2 @@
| gen_record_pat_field.rs:5:15:5:18 | RecordPatField | gen_record_pat_field.rs:5:15:5:15 | a |
| gen_record_pat_field.rs:5:21:5:24 | RecordPatField | gen_record_pat_field.rs:5:21:5:21 | b |
| gen_record_pat_field.rs:5:15:5:18 | a: 1 | gen_record_pat_field.rs:5:15:5:15 | a |
| gen_record_pat_field.rs:5:21:5:24 | b: 2 | gen_record_pat_field.rs:5:21:5:21 | b |

View File

@@ -1,2 +1,2 @@
| gen_record_pat_field.rs:5:15:5:18 | RecordPatField | gen_record_pat_field.rs:5:18:5:18 | 1 |
| gen_record_pat_field.rs:5:21:5:24 | RecordPatField | gen_record_pat_field.rs:5:24:5:24 | 2 |
| gen_record_pat_field.rs:5:15:5:18 | a: 1 | gen_record_pat_field.rs:5:18:5:18 | 1 |
| gen_record_pat_field.rs:5:21:5:24 | b: 2 | gen_record_pat_field.rs:5:24:5:24 | 2 |

View File

@@ -0,0 +1,7 @@
| gen_use_tree.rs:5:9:5:33 | UseTree | isGlob: | no | hasPath: | yes | hasRename: | no | hasUseTreeList: | no |
| gen_use_tree.rs:6:9:6:27 | UseTree | isGlob: | yes | hasPath: | yes | hasRename: | no | hasUseTreeList: | no |
| gen_use_tree.rs:7:9:7:46 | UseTree | isGlob: | no | hasPath: | yes | hasRename: | yes | hasUseTreeList: | no |
| gen_use_tree.rs:8:9:8:50 | UseTree | isGlob: | no | hasPath: | yes | hasRename: | no | hasUseTreeList: | yes |
| gen_use_tree.rs:8:28:8:31 | UseTree | isGlob: | no | hasPath: | yes | hasRename: | no | hasUseTreeList: | no |
| gen_use_tree.rs:8:34:8:40 | UseTree | isGlob: | no | hasPath: | yes | hasRename: | no | hasUseTreeList: | no |
| gen_use_tree.rs:8:43:8:49 | UseTree | isGlob: | no | hasPath: | yes | hasRename: | no | hasUseTreeList: | no |

View File

@@ -2,11 +2,13 @@
import codeql.rust.elements
import TestUtils
from UseTree x, string hasPath, string hasRename, string hasUseTreeList
from UseTree x, string isGlob, string hasPath, string hasRename, string hasUseTreeList
where
toBeTested(x) and
not x.isUnknown() and
(if x.isGlob() then isGlob = "yes" else isGlob = "no") and
(if x.hasPath() then hasPath = "yes" else hasPath = "no") and
(if x.hasRename() then hasRename = "yes" else hasRename = "no") and
if x.hasUseTreeList() then hasUseTreeList = "yes" else hasUseTreeList = "no"
select x, "hasPath:", hasPath, "hasRename:", hasRename, "hasUseTreeList:", hasUseTreeList
select x, "isGlob:", isGlob, "hasPath:", hasPath, "hasRename:", hasRename, "hasUseTreeList:",
hasUseTreeList

View File

@@ -0,0 +1,7 @@
| gen_use_tree.rs:5:9:5:33 | UseTree | gen_use_tree.rs:5:9:5:33 | ...::HashMap |
| gen_use_tree.rs:6:9:6:27 | UseTree | gen_use_tree.rs:6:9:6:24 | ...::collections |
| gen_use_tree.rs:7:9:7:46 | UseTree | gen_use_tree.rs:7:9:7:33 | ...::HashMap |
| gen_use_tree.rs:8:9:8:50 | UseTree | gen_use_tree.rs:8:9:8:24 | ...::collections |
| gen_use_tree.rs:8:28:8:31 | UseTree | gen_use_tree.rs:8:28:8:31 | self |
| gen_use_tree.rs:8:34:8:40 | UseTree | gen_use_tree.rs:8:34:8:40 | HashMap |
| gen_use_tree.rs:8:43:8:49 | UseTree | gen_use_tree.rs:8:43:8:49 | HashSet |

View File

@@ -0,0 +1 @@
| gen_use_tree.rs:7:9:7:46 | UseTree | gen_use_tree.rs:7:35:7:46 | Rename |

View File

@@ -0,0 +1 @@
| gen_use_tree.rs:8:9:8:50 | UseTree | gen_use_tree.rs:8:27:8:50 | UseTreeList |

View File

@@ -2,5 +2,8 @@
fn test_use_tree() -> () {
// A UseTree. For example:
todo!()
use std::collections::HashMap;
use std::collections::*;
use std::collections::HashMap as MyHashMap;
use std::collections::{self, HashMap, HashSet};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,23 @@
import rust
import codeql.rust.controlflow.ControlFlowGraph
import codeql.rust.controlflow.BasicBlocks
query predicate dominates(BasicBlock bb1, BasicBlock bb2) { bb1.dominates(bb2) }
query predicate postDominance(BasicBlock bb1, BasicBlock bb2) { bb1.postDominates(bb2) }
query predicate immediateDominator(BasicBlock bb1, BasicBlock bb2) {
bb1.getImmediateDominator() = bb2
}
query predicate controls(ConditionBasicBlock bb1, BasicBlock bb2, SuccessorType t) {
bb1.controls(bb2, t)
}
query predicate successor(ConditionBasicBlock bb1, BasicBlock bb2, SuccessorType t) {
bb1.getASuccessor(t) = bb2
}
query predicate joinBlockPredecessor(JoinBasicBlock bb1, BasicBlock bb2, int i) {
bb1.getJoinBlockPredecessor(i) = bb2
}

File diff suppressed because it is too large Load Diff

View File

@@ -134,6 +134,14 @@ mod if_expression {
}
}
fn test_if_without_else(b: bool) -> i64 {
let mut i = 3;
if b {
i += 1;
}
i
}
fn test_if_let_else(a: Option<i64>) -> i64 {
if let Some(n) = a {
n
@@ -157,6 +165,17 @@ mod if_expression {
}
}
fn test_nested_if_2(cond1: bool, cond2: bool) -> () {
if cond1 {
if cond2 {
println!("1");
} else {
println!("2");
}
println!("3");
};
}
fn test_nested_if_match(a: i64) -> i64 {
if (match a {
0 => true,

View File

@@ -20,21 +20,28 @@ edges
| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | provenance | |
| main.rs:41:26:44:5 | { ... } | main.rs:41:13:44:6 | pass_through(...) | provenance | |
| main.rs:43:9:43:18 | source(...) | main.rs:41:26:44:5 | { ... } | provenance | |
| main.rs:56:23:56:28 | ...: i64 | main.rs:57:14:57:14 | n | provenance | |
| main.rs:59:31:65:5 | { ... } | main.rs:77:13:77:25 | mn.get_data(...) | provenance | |
| main.rs:63:13:63:21 | source(...) | main.rs:59:31:65:5 | { ... } | provenance | |
| main.rs:66:28:66:33 | ...: i64 | main.rs:66:43:72:5 | { ... } | provenance | |
| main.rs:77:9:77:9 | a | main.rs:78:10:78:10 | a | provenance | |
| main.rs:77:13:77:25 | mn.get_data(...) | main.rs:77:9:77:9 | a | provenance | |
| main.rs:83:9:83:9 | a | main.rs:84:16:84:16 | a | provenance | |
| main.rs:83:13:83:21 | source(...) | main.rs:83:9:83:9 | a | provenance | |
| main.rs:84:16:84:16 | a | main.rs:56:23:56:28 | ...: i64 | provenance | |
| main.rs:89:9:89:9 | a | main.rs:90:29:90:29 | a | provenance | |
| main.rs:89:13:89:21 | source(...) | main.rs:89:9:89:9 | a | provenance | |
| main.rs:90:9:90:9 | b | main.rs:91:10:91:10 | b | provenance | |
| main.rs:90:13:90:30 | mn.data_through(...) | main.rs:90:9:90:9 | b | provenance | |
| main.rs:90:29:90:29 | a | main.rs:66:28:66:33 | ...: i64 | provenance | |
| main.rs:90:29:90:29 | a | main.rs:90:13:90:30 | mn.data_through(...) | provenance | |
| main.rs:49:9:49:9 | a | main.rs:55:26:55:26 | a | provenance | |
| main.rs:49:13:49:22 | source(...) | main.rs:49:9:49:9 | a | provenance | |
| main.rs:51:21:51:26 | ...: i64 | main.rs:51:36:53:5 | { ... } | provenance | |
| main.rs:55:9:55:9 | b | main.rs:56:10:56:10 | b | provenance | |
| main.rs:55:13:55:27 | pass_through(...) | main.rs:55:9:55:9 | b | provenance | |
| main.rs:55:26:55:26 | a | main.rs:51:21:51:26 | ...: i64 | provenance | |
| main.rs:55:26:55:26 | a | main.rs:55:13:55:27 | pass_through(...) | provenance | |
| main.rs:67:23:67:28 | ...: i64 | main.rs:68:14:68:14 | n | provenance | |
| main.rs:70:31:76:5 | { ... } | main.rs:88:13:88:25 | mn.get_data(...) | provenance | |
| main.rs:74:13:74:21 | source(...) | main.rs:70:31:76:5 | { ... } | provenance | |
| main.rs:77:28:77:33 | ...: i64 | main.rs:77:43:83:5 | { ... } | provenance | |
| main.rs:88:9:88:9 | a | main.rs:89:10:89:10 | a | provenance | |
| main.rs:88:13:88:25 | mn.get_data(...) | main.rs:88:9:88:9 | a | provenance | |
| main.rs:94:9:94:9 | a | main.rs:95:16:95:16 | a | provenance | |
| main.rs:94:13:94:21 | source(...) | main.rs:94:9:94:9 | a | provenance | |
| main.rs:95:16:95:16 | a | main.rs:67:23:67:28 | ...: i64 | provenance | |
| main.rs:100:9:100:9 | a | main.rs:101:29:101:29 | a | provenance | |
| main.rs:100:13:100:21 | source(...) | main.rs:100:9:100:9 | a | provenance | |
| main.rs:101:9:101:9 | b | main.rs:102:10:102:10 | b | provenance | |
| main.rs:101:13:101:30 | mn.data_through(...) | main.rs:101:9:101:9 | b | provenance | |
| main.rs:101:29:101:29 | a | main.rs:77:28:77:33 | ...: i64 | provenance | |
| main.rs:101:29:101:29 | a | main.rs:101:13:101:30 | mn.data_through(...) | provenance | |
nodes
| main.rs:12:28:14:1 | { ... } | semmle.label | { ... } |
| main.rs:13:5:13:13 | source(...) | semmle.label | source(...) |
@@ -59,34 +66,44 @@ nodes
| main.rs:41:26:44:5 | { ... } | semmle.label | { ... } |
| main.rs:43:9:43:18 | source(...) | semmle.label | source(...) |
| main.rs:45:10:45:10 | a | semmle.label | a |
| main.rs:56:23:56:28 | ...: i64 | semmle.label | ...: i64 |
| main.rs:57:14:57:14 | n | semmle.label | n |
| main.rs:59:31:65:5 | { ... } | semmle.label | { ... } |
| main.rs:63:13:63:21 | source(...) | semmle.label | source(...) |
| main.rs:66:28:66:33 | ...: i64 | semmle.label | ...: i64 |
| main.rs:66:43:72:5 | { ... } | semmle.label | { ... } |
| main.rs:77:9:77:9 | a | semmle.label | a |
| main.rs:77:13:77:25 | mn.get_data(...) | semmle.label | mn.get_data(...) |
| main.rs:78:10:78:10 | a | semmle.label | a |
| main.rs:83:9:83:9 | a | semmle.label | a |
| main.rs:83:13:83:21 | source(...) | semmle.label | source(...) |
| main.rs:84:16:84:16 | a | semmle.label | a |
| main.rs:89:9:89:9 | a | semmle.label | a |
| main.rs:89:13:89:21 | source(...) | semmle.label | source(...) |
| main.rs:90:9:90:9 | b | semmle.label | b |
| main.rs:90:13:90:30 | mn.data_through(...) | semmle.label | mn.data_through(...) |
| main.rs:90:29:90:29 | a | semmle.label | a |
| main.rs:91:10:91:10 | b | semmle.label | b |
| main.rs:49:9:49:9 | a | semmle.label | a |
| main.rs:49:13:49:22 | source(...) | semmle.label | source(...) |
| main.rs:51:21:51:26 | ...: i64 | semmle.label | ...: i64 |
| main.rs:51:36:53:5 | { ... } | semmle.label | { ... } |
| main.rs:55:9:55:9 | b | semmle.label | b |
| main.rs:55:13:55:27 | pass_through(...) | semmle.label | pass_through(...) |
| main.rs:55:26:55:26 | a | semmle.label | a |
| main.rs:56:10:56:10 | b | semmle.label | b |
| main.rs:67:23:67:28 | ...: i64 | semmle.label | ...: i64 |
| main.rs:68:14:68:14 | n | semmle.label | n |
| main.rs:70:31:76:5 | { ... } | semmle.label | { ... } |
| main.rs:74:13:74:21 | source(...) | semmle.label | source(...) |
| main.rs:77:28:77:33 | ...: i64 | semmle.label | ...: i64 |
| main.rs:77:43:83:5 | { ... } | semmle.label | { ... } |
| main.rs:88:9:88:9 | a | semmle.label | a |
| main.rs:88:13:88:25 | mn.get_data(...) | semmle.label | mn.get_data(...) |
| main.rs:89:10:89:10 | a | semmle.label | a |
| main.rs:94:9:94:9 | a | semmle.label | a |
| main.rs:94:13:94:21 | source(...) | semmle.label | source(...) |
| main.rs:95:16:95:16 | a | semmle.label | a |
| main.rs:100:9:100:9 | a | semmle.label | a |
| main.rs:100:13:100:21 | source(...) | semmle.label | source(...) |
| main.rs:101:9:101:9 | b | semmle.label | b |
| main.rs:101:13:101:30 | mn.data_through(...) | semmle.label | mn.data_through(...) |
| main.rs:101:29:101:29 | a | semmle.label | a |
| main.rs:102:10:102:10 | b | semmle.label | b |
subpaths
| main.rs:36:26:36:26 | a | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:36:13:36:27 | pass_through(...) |
| main.rs:41:26:44:5 | { ... } | main.rs:30:17:30:22 | ...: i64 | main.rs:30:32:32:1 | { ... } | main.rs:41:13:44:6 | pass_through(...) |
| main.rs:90:29:90:29 | a | main.rs:66:28:66:33 | ...: i64 | main.rs:66:43:72:5 | { ... } | main.rs:90:13:90:30 | mn.data_through(...) |
| main.rs:55:26:55:26 | a | main.rs:51:21:51:26 | ...: i64 | main.rs:51:36:53:5 | { ... } | main.rs:55:13:55:27 | pass_through(...) |
| main.rs:101:29:101:29 | a | main.rs:77:28:77:33 | ...: i64 | main.rs:77:43:83:5 | { ... } | main.rs:101:13:101:30 | mn.data_through(...) |
testFailures
#select
| main.rs:18:10:18:10 | a | main.rs:13:5:13:13 | source(...) | main.rs:18:10:18:10 | a | $@ | main.rs:13:5:13:13 | source(...) | source(...) |
| main.rs:22:10:22:10 | n | main.rs:26:13:26:21 | source(...) | main.rs:22:10:22:10 | n | $@ | main.rs:26:13:26:21 | source(...) | source(...) |
| main.rs:37:10:37:10 | b | main.rs:35:13:35:21 | source(...) | main.rs:37:10:37:10 | b | $@ | main.rs:35:13:35:21 | source(...) | source(...) |
| main.rs:45:10:45:10 | a | main.rs:43:9:43:18 | source(...) | main.rs:45:10:45:10 | a | $@ | main.rs:43:9:43:18 | source(...) | source(...) |
| main.rs:57:14:57:14 | n | main.rs:83:13:83:21 | source(...) | main.rs:57:14:57:14 | n | $@ | main.rs:83:13:83:21 | source(...) | source(...) |
| main.rs:78:10:78:10 | a | main.rs:63:13:63:21 | source(...) | main.rs:78:10:78:10 | a | $@ | main.rs:63:13:63:21 | source(...) | source(...) |
| main.rs:91:10:91:10 | b | main.rs:89:13:89:21 | source(...) | main.rs:91:10:91:10 | b | $@ | main.rs:89:13:89:21 | source(...) | source(...) |
| main.rs:56:10:56:10 | b | main.rs:49:13:49:22 | source(...) | main.rs:56:10:56:10 | b | $@ | main.rs:49:13:49:22 | source(...) | source(...) |
| main.rs:68:14:68:14 | n | main.rs:94:13:94:21 | source(...) | main.rs:68:14:68:14 | n | $@ | main.rs:94:13:94:21 | source(...) | source(...) |
| main.rs:89:10:89:10 | a | main.rs:74:13:74:21 | source(...) | main.rs:89:10:89:10 | a | $@ | main.rs:74:13:74:21 | source(...) | source(...) |
| main.rs:102:10:102:10 | b | main.rs:100:13:100:21 | source(...) | main.rs:102:10:102:10 | b | $@ | main.rs:100:13:100:21 | source(...) | source(...) |

View File

@@ -45,6 +45,17 @@ fn block_expression_as_argument() {
sink(a); // $ hasValueFlow=14
}
fn data_through_nested_function() {
let a = source(15);
fn pass_through(i: i64) -> i64 {
i
}
let b = pass_through(a);
sink(b); // $ hasValueFlow=15
}
// -----------------------------------------------------------------------------
// Data flow in, out, and through method.
@@ -127,6 +138,7 @@ fn main() {
data_out_of_call();
data_in_to_call();
data_through_call();
data_through_nested_function();
data_out_of_method();
data_in_to_method_call();

View File

@@ -10,26 +10,30 @@
| main.rs:41:13:44:6 | pass_through(...) | main.rs:30:1:32:1 | fn pass_through |
| main.rs:43:9:43:18 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:45:5:45:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:57:9:57:15 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:63:13:63:21 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:77:13:77:25 | mn.get_data(...) | main.rs:59:5:65:5 | fn get_data |
| main.rs:78:5:78:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:83:13:83:21 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:84:5:84:17 | mn.data_in(...) | main.rs:56:5:58:5 | fn data_in |
| main.rs:89:13:89:21 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:90:13:90:30 | mn.data_through(...) | main.rs:66:5:72:5 | fn data_through |
| main.rs:91:5:91:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:110:28:110:36 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:113:5:113:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:116:28:116:36 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:118:5:118:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:120:28:120:36 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:122:13:122:20 | a.add(...) | main.rs:103:5:106:5 | fn add |
| main.rs:123:5:123:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:127:5:127:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
| main.rs:128:5:128:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call |
| main.rs:129:5:129:23 | data_through_call(...) | main.rs:34:1:38:1 | fn data_through_call |
| main.rs:131:5:131:24 | data_out_of_method(...) | main.rs:75:1:79:1 | fn data_out_of_method |
| main.rs:132:5:132:28 | data_in_to_method_call(...) | main.rs:81:1:85:1 | fn data_in_to_method_call |
| main.rs:133:5:133:25 | data_through_method(...) | main.rs:87:1:92:1 | fn data_through_method |
| main.rs:135:5:135:31 | test_operator_overloading(...) | main.rs:109:1:124:1 | fn test_operator_overloading |
| main.rs:49:13:49:22 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:55:13:55:27 | pass_through(...) | main.rs:51:5:53:5 | fn pass_through |
| main.rs:56:5:56:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:68:9:68:15 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:74:13:74:21 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:88:13:88:25 | mn.get_data(...) | main.rs:70:5:76:5 | fn get_data |
| main.rs:89:5:89:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:94:13:94:21 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:95:5:95:17 | mn.data_in(...) | main.rs:67:5:69:5 | fn data_in |
| main.rs:100:13:100:21 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:101:13:101:30 | mn.data_through(...) | main.rs:77:5:83:5 | fn data_through |
| main.rs:102:5:102:11 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:121:28:121:36 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:124:5:124:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:127:28:127:36 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:129:5:129:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:131:28:131:36 | source(...) | main.rs:1:1:3:1 | fn source |
| main.rs:133:13:133:20 | a.add(...) | main.rs:114:5:117:5 | fn add |
| main.rs:134:5:134:17 | sink(...) | main.rs:5:1:7:1 | fn sink |
| main.rs:138:5:138:22 | data_out_of_call(...) | main.rs:16:1:19:1 | fn data_out_of_call |
| main.rs:139:5:139:21 | data_in_to_call(...) | main.rs:25:1:28:1 | fn data_in_to_call |
| main.rs:140:5:140:23 | data_through_call(...) | main.rs:34:1:38:1 | fn data_through_call |
| main.rs:141:5:141:34 | data_through_nested_function(...) | main.rs:48:1:57:1 | fn data_through_nested_function |
| main.rs:143:5:143:24 | data_out_of_method(...) | main.rs:86:1:90:1 | fn data_out_of_method |
| main.rs:144:5:144:28 | data_in_to_method_call(...) | main.rs:92:1:96:1 | fn data_in_to_method_call |
| main.rs:145:5:145:25 | data_through_method(...) | main.rs:98:1:103:1 | fn data_through_method |
| main.rs:147:5:147:31 | test_operator_overloading(...) | main.rs:120:1:135:1 | fn test_operator_overloading |

View File

@@ -1,2 +1,2 @@
identityLocalStep
| main.rs:394:7:394:18 | phi(default_name) | Node steps to itself |
| main.rs:425:9:425:20 | phi(default_name) | Node steps to itself |

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,19 @@
import codeql.rust.dataflow.DataFlow
import codeql.rust.dataflow.internal.DataFlowImpl
import utils.test.TranslateModels
query predicate localStep = DataFlow::localFlowStep/2;
private predicate provenance(string model) { RustDataFlow::simpleLocalFlowStep(_, _, model) }
private module Tm = TranslateModels<provenance/1>;
query predicate models = Tm::models/2;
query predicate localStep(Node nodeFrom, Node nodeTo, string model) {
exists(string madId |
RustDataFlow::simpleLocalFlowStep(nodeFrom, nodeTo, madId) and
Tm::translateModels(madId, model)
)
}
query predicate storeStep = RustDataFlow::storeStep/3;

View File

@@ -2,6 +2,10 @@ models
| 1 | Summary: lang:core; <crate::option::Option>::unwrap; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value |
| 2 | Summary: lang:core; <crate::option::Option>::unwrap_or; Argument[0]; ReturnValue; value |
| 3 | Summary: lang:core; <crate::option::Option>::unwrap_or; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value |
| 4 | Summary: lang:core; <crate::option::Option>::unwrap_or_else; Argument[0].ReturnValue; ReturnValue; value |
| 5 | Summary: lang:core; <crate::option::Option>::unwrap_or_else; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value |
| 6 | Summary: lang:core; <crate::result::Result>::expect; Argument[self].Variant[crate::result::Result::Ok(0)]; ReturnValue; value |
| 7 | Summary: lang:core; <crate::result::Result>::expect_err; Argument[self].Variant[crate::result::Result::Err(0)]; ReturnValue; value |
edges
| main.rs:19:9:19:9 | s | main.rs:20:10:20:10 | s | provenance | |
| main.rs:19:13:19:21 | source(...) | main.rs:19:9:19:9 | s | provenance | |
@@ -45,115 +49,144 @@ edges
| main.rs:148:12:148:21 | source(...) | main.rs:147:13:150:5 | Point {...} [Point.x] | provenance | |
| main.rs:151:9:151:28 | Point {...} [Point.x] | main.rs:151:20:151:20 | a | provenance | |
| main.rs:151:20:151:20 | a | main.rs:152:10:152:10 | a | provenance | |
| main.rs:198:9:198:10 | s1 [Some] | main.rs:200:11:200:12 | s1 [Some] | provenance | |
| main.rs:198:14:198:37 | ...::Some(...) [Some] | main.rs:198:9:198:10 | s1 [Some] | provenance | |
| main.rs:198:27:198:36 | source(...) | main.rs:198:14:198:37 | ...::Some(...) [Some] | provenance | |
| main.rs:200:11:200:12 | s1 [Some] | main.rs:201:9:201:23 | ...::Some(...) [Some] | provenance | |
| main.rs:201:9:201:23 | ...::Some(...) [Some] | main.rs:201:22:201:22 | n | provenance | |
| main.rs:201:22:201:22 | n | main.rs:201:33:201:33 | n | provenance | |
| main.rs:175:9:175:9 | y | main.rs:177:30:177:30 | y | provenance | |
| main.rs:175:13:175:22 | source(...) | main.rs:175:9:175:9 | y | provenance | |
| main.rs:176:9:176:9 | p [Point3D.plane, Point.y] | main.rs:180:11:180:11 | p [Point3D.plane, Point.y] | provenance | |
| main.rs:176:13:179:5 | Point3D {...} [Point3D.plane, Point.y] | main.rs:176:9:176:9 | p [Point3D.plane, Point.y] | provenance | |
| main.rs:177:16:177:32 | Point {...} [Point.y] | main.rs:176:13:179:5 | Point3D {...} [Point3D.plane, Point.y] | provenance | |
| main.rs:177:30:177:30 | y | main.rs:177:16:177:32 | Point {...} [Point.y] | provenance | |
| main.rs:180:11:180:11 | p [Point3D.plane, Point.y] | main.rs:181:9:184:9 | Point3D {...} [Point3D.plane, Point.y] | provenance | |
| main.rs:181:9:184:9 | Point3D {...} [Point3D.plane, Point.y] | main.rs:182:20:182:33 | Point {...} [Point.y] | provenance | |
| main.rs:182:20:182:33 | Point {...} [Point.y] | main.rs:182:31:182:31 | y | provenance | |
| main.rs:182:31:182:31 | y | main.rs:186:18:186:18 | y | provenance | |
| main.rs:195:9:195:9 | s [MyTupleStruct(0)] | main.rs:199:11:199:11 | s [MyTupleStruct(0)] | provenance | |
| main.rs:195:13:195:40 | MyTupleStruct(...) [MyTupleStruct(0)] | main.rs:195:9:195:9 | s [MyTupleStruct(0)] | provenance | |
| main.rs:195:27:195:36 | source(...) | main.rs:195:13:195:40 | MyTupleStruct(...) [MyTupleStruct(0)] | provenance | |
| main.rs:199:11:199:11 | s [MyTupleStruct(0)] | main.rs:200:9:200:27 | MyTupleStruct(...) [MyTupleStruct(0)] | provenance | |
| main.rs:200:9:200:27 | MyTupleStruct(...) [MyTupleStruct(0)] | main.rs:200:23:200:23 | x | provenance | |
| main.rs:200:23:200:23 | x | main.rs:201:18:201:18 | x | provenance | |
| main.rs:211:9:211:10 | s1 [Some] | main.rs:213:11:213:12 | s1 [Some] | provenance | |
| main.rs:211:14:211:29 | Some(...) [Some] | main.rs:211:9:211:10 | s1 [Some] | provenance | |
| main.rs:211:19:211:28 | source(...) | main.rs:211:14:211:29 | Some(...) [Some] | provenance | |
| main.rs:213:11:213:12 | s1 [Some] | main.rs:214:9:214:15 | Some(...) [Some] | provenance | |
| main.rs:214:9:214:15 | Some(...) [Some] | main.rs:214:14:214:14 | n | provenance | |
| main.rs:214:14:214:14 | n | main.rs:214:25:214:25 | n | provenance | |
| main.rs:224:9:224:10 | s1 [Some] | main.rs:225:10:225:11 | s1 [Some] | provenance | |
| main.rs:211:14:211:37 | ...::Some(...) [Some] | main.rs:211:9:211:10 | s1 [Some] | provenance | |
| main.rs:211:27:211:36 | source(...) | main.rs:211:14:211:37 | ...::Some(...) [Some] | provenance | |
| main.rs:213:11:213:12 | s1 [Some] | main.rs:214:9:214:23 | ...::Some(...) [Some] | provenance | |
| main.rs:214:9:214:23 | ...::Some(...) [Some] | main.rs:214:22:214:22 | n | provenance | |
| main.rs:214:22:214:22 | n | main.rs:214:33:214:33 | n | provenance | |
| main.rs:224:9:224:10 | s1 [Some] | main.rs:226:11:226:12 | s1 [Some] | provenance | |
| main.rs:224:14:224:29 | Some(...) [Some] | main.rs:224:9:224:10 | s1 [Some] | provenance | |
| main.rs:224:19:224:28 | source(...) | main.rs:224:14:224:29 | Some(...) [Some] | provenance | |
| main.rs:225:10:225:11 | s1 [Some] | main.rs:225:10:225:20 | s1.unwrap(...) | provenance | MaD:1 |
| main.rs:229:9:229:10 | s1 [Some] | main.rs:230:10:230:11 | s1 [Some] | provenance | |
| main.rs:229:14:229:29 | Some(...) [Some] | main.rs:229:9:229:10 | s1 [Some] | provenance | |
| main.rs:229:19:229:28 | source(...) | main.rs:229:14:229:29 | Some(...) [Some] | provenance | |
| main.rs:230:10:230:11 | s1 [Some] | main.rs:230:10:230:24 | s1.unwrap_or(...) | provenance | MaD:3 |
| main.rs:233:23:233:32 | source(...) | main.rs:233:10:233:33 | s2.unwrap_or(...) | provenance | MaD:2 |
| main.rs:237:9:237:10 | s1 [Some] | main.rs:239:14:239:15 | s1 [Some] | provenance | |
| main.rs:226:11:226:12 | s1 [Some] | main.rs:227:9:227:15 | Some(...) [Some] | provenance | |
| main.rs:227:9:227:15 | Some(...) [Some] | main.rs:227:14:227:14 | n | provenance | |
| main.rs:227:14:227:14 | n | main.rs:227:25:227:25 | n | provenance | |
| main.rs:237:9:237:10 | s1 [Some] | main.rs:238:10:238:11 | s1 [Some] | provenance | |
| main.rs:237:14:237:29 | Some(...) [Some] | main.rs:237:9:237:10 | s1 [Some] | provenance | |
| main.rs:237:19:237:28 | source(...) | main.rs:237:14:237:29 | Some(...) [Some] | provenance | |
| main.rs:239:9:239:10 | i1 | main.rs:240:10:240:11 | i1 | provenance | |
| main.rs:239:14:239:15 | s1 [Some] | main.rs:239:14:239:16 | TryExpr | provenance | |
| main.rs:239:14:239:16 | TryExpr | main.rs:239:9:239:10 | i1 | provenance | |
| main.rs:246:9:246:10 | s1 [Ok] | main.rs:249:14:249:15 | s1 [Ok] | provenance | |
| main.rs:246:32:246:45 | Ok(...) [Ok] | main.rs:246:9:246:10 | s1 [Ok] | provenance | |
| main.rs:246:35:246:44 | source(...) | main.rs:246:32:246:45 | Ok(...) [Ok] | provenance | |
| main.rs:249:9:249:10 | i1 | main.rs:251:10:251:11 | i1 | provenance | |
| main.rs:249:14:249:15 | s1 [Ok] | main.rs:249:14:249:16 | TryExpr | provenance | |
| main.rs:249:14:249:16 | TryExpr | main.rs:249:9:249:10 | i1 | provenance | |
| main.rs:264:9:264:10 | s1 [A] | main.rs:266:11:266:12 | s1 [A] | provenance | |
| main.rs:264:14:264:39 | ...::A(...) [A] | main.rs:264:9:264:10 | s1 [A] | provenance | |
| main.rs:264:29:264:38 | source(...) | main.rs:264:14:264:39 | ...::A(...) [A] | provenance | |
| main.rs:266:11:266:12 | s1 [A] | main.rs:267:9:267:25 | ...::A(...) [A] | provenance | |
| main.rs:266:11:266:12 | s1 [A] | main.rs:270:11:270:12 | s1 [A] | provenance | |
| main.rs:267:9:267:25 | ...::A(...) [A] | main.rs:267:24:267:24 | n | provenance | |
| main.rs:267:24:267:24 | n | main.rs:267:35:267:35 | n | provenance | |
| main.rs:270:11:270:12 | s1 [A] | main.rs:271:9:271:25 | ...::A(...) [A] | provenance | |
| main.rs:271:9:271:25 | ...::A(...) [A] | main.rs:271:24:271:24 | n | provenance | |
| main.rs:271:24:271:24 | n | main.rs:271:55:271:55 | n | provenance | |
| main.rs:282:9:282:10 | s1 [A] | main.rs:284:11:284:12 | s1 [A] | provenance | |
| main.rs:282:14:282:26 | A(...) [A] | main.rs:282:9:282:10 | s1 [A] | provenance | |
| main.rs:282:16:282:25 | source(...) | main.rs:282:14:282:26 | A(...) [A] | provenance | |
| main.rs:284:11:284:12 | s1 [A] | main.rs:285:9:285:12 | A(...) [A] | provenance | |
| main.rs:284:11:284:12 | s1 [A] | main.rs:288:11:288:12 | s1 [A] | provenance | |
| main.rs:285:9:285:12 | A(...) [A] | main.rs:285:11:285:11 | n | provenance | |
| main.rs:285:11:285:11 | n | main.rs:285:22:285:22 | n | provenance | |
| main.rs:288:11:288:12 | s1 [A] | main.rs:289:9:289:12 | A(...) [A] | provenance | |
| main.rs:289:9:289:12 | A(...) [A] | main.rs:289:11:289:11 | n | provenance | |
| main.rs:289:11:289:11 | n | main.rs:289:29:289:29 | n | provenance | |
| main.rs:303:9:303:10 | s1 [C] | main.rs:307:11:307:12 | s1 [C] | provenance | |
| main.rs:303:14:305:5 | ...::C {...} [C] | main.rs:303:9:303:10 | s1 [C] | provenance | |
| main.rs:304:18:304:27 | source(...) | main.rs:303:14:305:5 | ...::C {...} [C] | provenance | |
| main.rs:307:11:307:12 | s1 [C] | main.rs:308:9:308:38 | ...::C {...} [C] | provenance | |
| main.rs:307:11:307:12 | s1 [C] | main.rs:311:11:311:12 | s1 [C] | provenance | |
| main.rs:308:9:308:38 | ...::C {...} [C] | main.rs:308:36:308:36 | n | provenance | |
| main.rs:308:36:308:36 | n | main.rs:308:48:308:48 | n | provenance | |
| main.rs:311:11:311:12 | s1 [C] | main.rs:312:9:312:38 | ...::C {...} [C] | provenance | |
| main.rs:312:9:312:38 | ...::C {...} [C] | main.rs:312:36:312:36 | n | provenance | |
| main.rs:312:36:312:36 | n | main.rs:312:81:312:81 | n | provenance | |
| main.rs:323:9:323:10 | s1 [C] | main.rs:327:11:327:12 | s1 [C] | provenance | |
| main.rs:323:14:325:5 | C {...} [C] | main.rs:323:9:323:10 | s1 [C] | provenance | |
| main.rs:324:18:324:27 | source(...) | main.rs:323:14:325:5 | C {...} [C] | provenance | |
| main.rs:327:11:327:12 | s1 [C] | main.rs:328:9:328:24 | C {...} [C] | provenance | |
| main.rs:327:11:327:12 | s1 [C] | main.rs:331:11:331:12 | s1 [C] | provenance | |
| main.rs:328:9:328:24 | C {...} [C] | main.rs:328:22:328:22 | n | provenance | |
| main.rs:328:22:328:22 | n | main.rs:328:34:328:34 | n | provenance | |
| main.rs:331:11:331:12 | s1 [C] | main.rs:332:9:332:24 | C {...} [C] | provenance | |
| main.rs:332:9:332:24 | C {...} [C] | main.rs:332:22:332:22 | n | provenance | |
| main.rs:332:22:332:22 | n | main.rs:332:53:332:53 | n | provenance | |
| main.rs:344:9:344:12 | arr1 [array[]] | main.rs:345:14:345:17 | arr1 [array[]] | provenance | |
| main.rs:344:16:344:33 | [...] [array[]] | main.rs:344:9:344:12 | arr1 [array[]] | provenance | |
| main.rs:344:23:344:32 | source(...) | main.rs:344:16:344:33 | [...] [array[]] | provenance | |
| main.rs:345:9:345:10 | n1 | main.rs:346:10:346:11 | n1 | provenance | |
| main.rs:345:14:345:17 | arr1 [array[]] | main.rs:345:14:345:20 | arr1[2] | provenance | |
| main.rs:345:14:345:20 | arr1[2] | main.rs:345:9:345:10 | n1 | provenance | |
| main.rs:348:9:348:12 | arr2 [array[]] | main.rs:349:14:349:17 | arr2 [array[]] | provenance | |
| main.rs:348:16:348:31 | [...; 10] [array[]] | main.rs:348:9:348:12 | arr2 [array[]] | provenance | |
| main.rs:348:17:348:26 | source(...) | main.rs:348:16:348:31 | [...; 10] [array[]] | provenance | |
| main.rs:349:9:349:10 | n2 | main.rs:350:10:350:11 | n2 | provenance | |
| main.rs:349:14:349:17 | arr2 [array[]] | main.rs:349:14:349:20 | arr2[4] | provenance | |
| main.rs:349:14:349:20 | arr2[4] | main.rs:349:9:349:10 | n2 | provenance | |
| main.rs:358:9:358:12 | arr1 [array[]] | main.rs:359:15:359:18 | arr1 [array[]] | provenance | |
| main.rs:358:16:358:33 | [...] [array[]] | main.rs:358:9:358:12 | arr1 [array[]] | provenance | |
| main.rs:358:23:358:32 | source(...) | main.rs:358:16:358:33 | [...] [array[]] | provenance | |
| main.rs:359:9:359:10 | n1 | main.rs:360:14:360:15 | n1 | provenance | |
| main.rs:359:15:359:18 | arr1 [array[]] | main.rs:359:9:359:10 | n1 | provenance | |
| main.rs:370:9:370:12 | arr1 [array[]] | main.rs:371:11:371:14 | arr1 [array[]] | provenance | |
| main.rs:370:16:370:33 | [...] [array[]] | main.rs:370:9:370:12 | arr1 [array[]] | provenance | |
| main.rs:370:23:370:32 | source(...) | main.rs:370:16:370:33 | [...] [array[]] | provenance | |
| main.rs:371:11:371:14 | arr1 [array[]] | main.rs:372:9:372:17 | SlicePat [array[]] | provenance | |
| main.rs:372:9:372:17 | SlicePat [array[]] | main.rs:372:10:372:10 | a | provenance | |
| main.rs:372:9:372:17 | SlicePat [array[]] | main.rs:372:13:372:13 | b | provenance | |
| main.rs:372:9:372:17 | SlicePat [array[]] | main.rs:372:16:372:16 | c | provenance | |
| main.rs:372:10:372:10 | a | main.rs:373:18:373:18 | a | provenance | |
| main.rs:372:13:372:13 | b | main.rs:374:18:374:18 | b | provenance | |
| main.rs:372:16:372:16 | c | main.rs:375:18:375:18 | c | provenance | |
| main.rs:384:5:384:11 | [post] mut_arr [array[]] | main.rs:385:13:385:19 | mut_arr [array[]] | provenance | |
| main.rs:384:5:384:11 | [post] mut_arr [array[]] | main.rs:387:10:387:16 | mut_arr [array[]] | provenance | |
| main.rs:384:18:384:27 | source(...) | main.rs:384:5:384:11 | [post] mut_arr [array[]] | provenance | |
| main.rs:385:9:385:9 | d | main.rs:386:10:386:10 | d | provenance | |
| main.rs:385:13:385:19 | mut_arr [array[]] | main.rs:385:13:385:22 | mut_arr[1] | provenance | |
| main.rs:385:13:385:22 | mut_arr[1] | main.rs:385:9:385:9 | d | provenance | |
| main.rs:387:10:387:16 | mut_arr [array[]] | main.rs:387:10:387:19 | mut_arr[0] | provenance | |
| main.rs:410:9:410:9 | s | main.rs:411:10:411:10 | s | provenance | |
| main.rs:410:25:410:26 | source(...) | main.rs:410:9:410:9 | s | provenance | |
| main.rs:238:10:238:11 | s1 [Some] | main.rs:238:10:238:20 | s1.unwrap(...) | provenance | MaD:1 |
| main.rs:242:9:242:10 | s1 [Some] | main.rs:243:10:243:11 | s1 [Some] | provenance | |
| main.rs:242:14:242:29 | Some(...) [Some] | main.rs:242:9:242:10 | s1 [Some] | provenance | |
| main.rs:242:19:242:28 | source(...) | main.rs:242:14:242:29 | Some(...) [Some] | provenance | |
| main.rs:243:10:243:11 | s1 [Some] | main.rs:243:10:243:24 | s1.unwrap_or(...) | provenance | MaD:3 |
| main.rs:246:23:246:32 | source(...) | main.rs:246:10:246:33 | s2.unwrap_or(...) | provenance | MaD:2 |
| main.rs:250:9:250:10 | s1 [Some] | main.rs:251:10:251:11 | s1 [Some] | provenance | |
| main.rs:250:14:250:29 | Some(...) [Some] | main.rs:250:9:250:10 | s1 [Some] | provenance | |
| main.rs:250:19:250:28 | source(...) | main.rs:250:14:250:29 | Some(...) [Some] | provenance | |
| main.rs:251:10:251:11 | s1 [Some] | main.rs:251:10:251:32 | s1.unwrap_or_else(...) | provenance | MaD:5 |
| main.rs:254:31:254:40 | source(...) | main.rs:254:10:254:41 | s2.unwrap_or_else(...) | provenance | MaD:4 |
| main.rs:258:9:258:10 | s1 [Some] | main.rs:260:14:260:15 | s1 [Some] | provenance | |
| main.rs:258:14:258:29 | Some(...) [Some] | main.rs:258:9:258:10 | s1 [Some] | provenance | |
| main.rs:258:19:258:28 | source(...) | main.rs:258:14:258:29 | Some(...) [Some] | provenance | |
| main.rs:260:9:260:10 | i1 | main.rs:261:10:261:11 | i1 | provenance | |
| main.rs:260:14:260:15 | s1 [Some] | main.rs:260:14:260:16 | TryExpr | provenance | |
| main.rs:260:14:260:16 | TryExpr | main.rs:260:9:260:10 | i1 | provenance | |
| main.rs:267:9:267:10 | s1 [Ok] | main.rs:270:14:270:15 | s1 [Ok] | provenance | |
| main.rs:267:32:267:45 | Ok(...) [Ok] | main.rs:267:9:267:10 | s1 [Ok] | provenance | |
| main.rs:267:35:267:44 | source(...) | main.rs:267:32:267:45 | Ok(...) [Ok] | provenance | |
| main.rs:270:9:270:10 | i1 | main.rs:272:10:272:11 | i1 | provenance | |
| main.rs:270:14:270:15 | s1 [Ok] | main.rs:270:14:270:16 | TryExpr | provenance | |
| main.rs:270:14:270:16 | TryExpr | main.rs:270:9:270:10 | i1 | provenance | |
| main.rs:280:9:280:10 | s1 [Ok] | main.rs:281:10:281:11 | s1 [Ok] | provenance | |
| main.rs:280:32:280:45 | Ok(...) [Ok] | main.rs:280:9:280:10 | s1 [Ok] | provenance | |
| main.rs:280:35:280:44 | source(...) | main.rs:280:32:280:45 | Ok(...) [Ok] | provenance | |
| main.rs:281:10:281:11 | s1 [Ok] | main.rs:281:10:281:22 | s1.expect(...) | provenance | MaD:6 |
| main.rs:284:9:284:10 | s2 [Err] | main.rs:286:10:286:11 | s2 [Err] | provenance | |
| main.rs:284:32:284:46 | Err(...) [Err] | main.rs:284:9:284:10 | s2 [Err] | provenance | |
| main.rs:284:36:284:45 | source(...) | main.rs:284:32:284:46 | Err(...) [Err] | provenance | |
| main.rs:286:10:286:11 | s2 [Err] | main.rs:286:10:286:26 | s2.expect_err(...) | provenance | MaD:7 |
| main.rs:295:9:295:10 | s1 [A] | main.rs:297:11:297:12 | s1 [A] | provenance | |
| main.rs:295:14:295:39 | ...::A(...) [A] | main.rs:295:9:295:10 | s1 [A] | provenance | |
| main.rs:295:29:295:38 | source(...) | main.rs:295:14:295:39 | ...::A(...) [A] | provenance | |
| main.rs:297:11:297:12 | s1 [A] | main.rs:298:9:298:25 | ...::A(...) [A] | provenance | |
| main.rs:297:11:297:12 | s1 [A] | main.rs:301:11:301:12 | s1 [A] | provenance | |
| main.rs:298:9:298:25 | ...::A(...) [A] | main.rs:298:24:298:24 | n | provenance | |
| main.rs:298:24:298:24 | n | main.rs:298:35:298:35 | n | provenance | |
| main.rs:301:11:301:12 | s1 [A] | main.rs:302:9:302:25 | ...::A(...) [A] | provenance | |
| main.rs:302:9:302:25 | ...::A(...) [A] | main.rs:302:24:302:24 | n | provenance | |
| main.rs:302:24:302:24 | n | main.rs:302:55:302:55 | n | provenance | |
| main.rs:313:9:313:10 | s1 [A] | main.rs:315:11:315:12 | s1 [A] | provenance | |
| main.rs:313:14:313:26 | A(...) [A] | main.rs:313:9:313:10 | s1 [A] | provenance | |
| main.rs:313:16:313:25 | source(...) | main.rs:313:14:313:26 | A(...) [A] | provenance | |
| main.rs:315:11:315:12 | s1 [A] | main.rs:316:9:316:12 | A(...) [A] | provenance | |
| main.rs:315:11:315:12 | s1 [A] | main.rs:319:11:319:12 | s1 [A] | provenance | |
| main.rs:316:9:316:12 | A(...) [A] | main.rs:316:11:316:11 | n | provenance | |
| main.rs:316:11:316:11 | n | main.rs:316:22:316:22 | n | provenance | |
| main.rs:319:11:319:12 | s1 [A] | main.rs:320:9:320:12 | A(...) [A] | provenance | |
| main.rs:320:9:320:12 | A(...) [A] | main.rs:320:11:320:11 | n | provenance | |
| main.rs:320:11:320:11 | n | main.rs:320:29:320:29 | n | provenance | |
| main.rs:334:9:334:10 | s1 [C] | main.rs:338:11:338:12 | s1 [C] | provenance | |
| main.rs:334:14:336:5 | ...::C {...} [C] | main.rs:334:9:334:10 | s1 [C] | provenance | |
| main.rs:335:18:335:27 | source(...) | main.rs:334:14:336:5 | ...::C {...} [C] | provenance | |
| main.rs:338:11:338:12 | s1 [C] | main.rs:339:9:339:38 | ...::C {...} [C] | provenance | |
| main.rs:338:11:338:12 | s1 [C] | main.rs:342:11:342:12 | s1 [C] | provenance | |
| main.rs:339:9:339:38 | ...::C {...} [C] | main.rs:339:36:339:36 | n | provenance | |
| main.rs:339:36:339:36 | n | main.rs:339:48:339:48 | n | provenance | |
| main.rs:342:11:342:12 | s1 [C] | main.rs:343:9:343:38 | ...::C {...} [C] | provenance | |
| main.rs:343:9:343:38 | ...::C {...} [C] | main.rs:343:36:343:36 | n | provenance | |
| main.rs:343:36:343:36 | n | main.rs:343:81:343:81 | n | provenance | |
| main.rs:354:9:354:10 | s1 [C] | main.rs:358:11:358:12 | s1 [C] | provenance | |
| main.rs:354:14:356:5 | C {...} [C] | main.rs:354:9:354:10 | s1 [C] | provenance | |
| main.rs:355:18:355:27 | source(...) | main.rs:354:14:356:5 | C {...} [C] | provenance | |
| main.rs:358:11:358:12 | s1 [C] | main.rs:359:9:359:24 | C {...} [C] | provenance | |
| main.rs:358:11:358:12 | s1 [C] | main.rs:362:11:362:12 | s1 [C] | provenance | |
| main.rs:359:9:359:24 | C {...} [C] | main.rs:359:22:359:22 | n | provenance | |
| main.rs:359:22:359:22 | n | main.rs:359:34:359:34 | n | provenance | |
| main.rs:362:11:362:12 | s1 [C] | main.rs:363:9:363:24 | C {...} [C] | provenance | |
| main.rs:363:9:363:24 | C {...} [C] | main.rs:363:22:363:22 | n | provenance | |
| main.rs:363:22:363:22 | n | main.rs:363:53:363:53 | n | provenance | |
| main.rs:375:9:375:12 | arr1 [element] | main.rs:376:14:376:17 | arr1 [element] | provenance | |
| main.rs:375:16:375:33 | [...] [element] | main.rs:375:9:375:12 | arr1 [element] | provenance | |
| main.rs:375:23:375:32 | source(...) | main.rs:375:16:375:33 | [...] [element] | provenance | |
| main.rs:376:9:376:10 | n1 | main.rs:377:10:377:11 | n1 | provenance | |
| main.rs:376:14:376:17 | arr1 [element] | main.rs:376:14:376:20 | arr1[2] | provenance | |
| main.rs:376:14:376:20 | arr1[2] | main.rs:376:9:376:10 | n1 | provenance | |
| main.rs:379:9:379:12 | arr2 [element] | main.rs:380:14:380:17 | arr2 [element] | provenance | |
| main.rs:379:16:379:31 | [...; 10] [element] | main.rs:379:9:379:12 | arr2 [element] | provenance | |
| main.rs:379:17:379:26 | source(...) | main.rs:379:16:379:31 | [...; 10] [element] | provenance | |
| main.rs:380:9:380:10 | n2 | main.rs:381:10:381:11 | n2 | provenance | |
| main.rs:380:14:380:17 | arr2 [element] | main.rs:380:14:380:20 | arr2[4] | provenance | |
| main.rs:380:14:380:20 | arr2[4] | main.rs:380:9:380:10 | n2 | provenance | |
| main.rs:389:9:389:12 | arr1 [element] | main.rs:390:15:390:18 | arr1 [element] | provenance | |
| main.rs:389:16:389:33 | [...] [element] | main.rs:389:9:389:12 | arr1 [element] | provenance | |
| main.rs:389:23:389:32 | source(...) | main.rs:389:16:389:33 | [...] [element] | provenance | |
| main.rs:390:9:390:10 | n1 | main.rs:391:14:391:15 | n1 | provenance | |
| main.rs:390:15:390:18 | arr1 [element] | main.rs:390:9:390:10 | n1 | provenance | |
| main.rs:401:9:401:12 | arr1 [element] | main.rs:402:11:402:14 | arr1 [element] | provenance | |
| main.rs:401:16:401:33 | [...] [element] | main.rs:401:9:401:12 | arr1 [element] | provenance | |
| main.rs:401:23:401:32 | source(...) | main.rs:401:16:401:33 | [...] [element] | provenance | |
| main.rs:402:11:402:14 | arr1 [element] | main.rs:403:9:403:17 | SlicePat [element] | provenance | |
| main.rs:403:9:403:17 | SlicePat [element] | main.rs:403:10:403:10 | a | provenance | |
| main.rs:403:9:403:17 | SlicePat [element] | main.rs:403:13:403:13 | b | provenance | |
| main.rs:403:9:403:17 | SlicePat [element] | main.rs:403:16:403:16 | c | provenance | |
| main.rs:403:10:403:10 | a | main.rs:404:18:404:18 | a | provenance | |
| main.rs:403:13:403:13 | b | main.rs:405:18:405:18 | b | provenance | |
| main.rs:403:16:403:16 | c | main.rs:406:18:406:18 | c | provenance | |
| main.rs:415:5:415:11 | [post] mut_arr [element] | main.rs:416:13:416:19 | mut_arr [element] | provenance | |
| main.rs:415:5:415:11 | [post] mut_arr [element] | main.rs:418:10:418:16 | mut_arr [element] | provenance | |
| main.rs:415:18:415:27 | source(...) | main.rs:415:5:415:11 | [post] mut_arr [element] | provenance | |
| main.rs:416:9:416:9 | d | main.rs:417:10:417:10 | d | provenance | |
| main.rs:416:13:416:19 | mut_arr [element] | main.rs:416:13:416:22 | mut_arr[1] | provenance | |
| main.rs:416:13:416:22 | mut_arr[1] | main.rs:416:9:416:9 | d | provenance | |
| main.rs:418:10:418:16 | mut_arr [element] | main.rs:418:10:418:19 | mut_arr[0] | provenance | |
| main.rs:441:9:441:9 | s | main.rs:442:10:442:10 | s | provenance | |
| main.rs:441:25:441:26 | source(...) | main.rs:441:9:441:9 | s | provenance | |
nodes
| main.rs:15:10:15:18 | source(...) | semmle.label | source(...) |
| main.rs:19:9:19:9 | s | semmle.label | s |
@@ -209,132 +242,167 @@ nodes
| main.rs:151:9:151:28 | Point {...} [Point.x] | semmle.label | Point {...} [Point.x] |
| main.rs:151:20:151:20 | a | semmle.label | a |
| main.rs:152:10:152:10 | a | semmle.label | a |
| main.rs:198:9:198:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:198:14:198:37 | ...::Some(...) [Some] | semmle.label | ...::Some(...) [Some] |
| main.rs:198:27:198:36 | source(...) | semmle.label | source(...) |
| main.rs:200:11:200:12 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:201:9:201:23 | ...::Some(...) [Some] | semmle.label | ...::Some(...) [Some] |
| main.rs:201:22:201:22 | n | semmle.label | n |
| main.rs:201:33:201:33 | n | semmle.label | n |
| main.rs:175:9:175:9 | y | semmle.label | y |
| main.rs:175:13:175:22 | source(...) | semmle.label | source(...) |
| main.rs:176:9:176:9 | p [Point3D.plane, Point.y] | semmle.label | p [Point3D.plane, Point.y] |
| main.rs:176:13:179:5 | Point3D {...} [Point3D.plane, Point.y] | semmle.label | Point3D {...} [Point3D.plane, Point.y] |
| main.rs:177:16:177:32 | Point {...} [Point.y] | semmle.label | Point {...} [Point.y] |
| main.rs:177:30:177:30 | y | semmle.label | y |
| main.rs:180:11:180:11 | p [Point3D.plane, Point.y] | semmle.label | p [Point3D.plane, Point.y] |
| main.rs:181:9:184:9 | Point3D {...} [Point3D.plane, Point.y] | semmle.label | Point3D {...} [Point3D.plane, Point.y] |
| main.rs:182:20:182:33 | Point {...} [Point.y] | semmle.label | Point {...} [Point.y] |
| main.rs:182:31:182:31 | y | semmle.label | y |
| main.rs:186:18:186:18 | y | semmle.label | y |
| main.rs:195:9:195:9 | s [MyTupleStruct(0)] | semmle.label | s [MyTupleStruct(0)] |
| main.rs:195:13:195:40 | MyTupleStruct(...) [MyTupleStruct(0)] | semmle.label | MyTupleStruct(...) [MyTupleStruct(0)] |
| main.rs:195:27:195:36 | source(...) | semmle.label | source(...) |
| main.rs:199:11:199:11 | s [MyTupleStruct(0)] | semmle.label | s [MyTupleStruct(0)] |
| main.rs:200:9:200:27 | MyTupleStruct(...) [MyTupleStruct(0)] | semmle.label | MyTupleStruct(...) [MyTupleStruct(0)] |
| main.rs:200:23:200:23 | x | semmle.label | x |
| main.rs:201:18:201:18 | x | semmle.label | x |
| main.rs:211:9:211:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:211:14:211:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:211:19:211:28 | source(...) | semmle.label | source(...) |
| main.rs:211:14:211:37 | ...::Some(...) [Some] | semmle.label | ...::Some(...) [Some] |
| main.rs:211:27:211:36 | source(...) | semmle.label | source(...) |
| main.rs:213:11:213:12 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:214:9:214:15 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:214:14:214:14 | n | semmle.label | n |
| main.rs:214:25:214:25 | n | semmle.label | n |
| main.rs:214:9:214:23 | ...::Some(...) [Some] | semmle.label | ...::Some(...) [Some] |
| main.rs:214:22:214:22 | n | semmle.label | n |
| main.rs:214:33:214:33 | n | semmle.label | n |
| main.rs:224:9:224:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:224:14:224:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:224:19:224:28 | source(...) | semmle.label | source(...) |
| main.rs:225:10:225:11 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:225:10:225:20 | s1.unwrap(...) | semmle.label | s1.unwrap(...) |
| main.rs:229:9:229:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:229:14:229:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:229:19:229:28 | source(...) | semmle.label | source(...) |
| main.rs:230:10:230:11 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:230:10:230:24 | s1.unwrap_or(...) | semmle.label | s1.unwrap_or(...) |
| main.rs:233:10:233:33 | s2.unwrap_or(...) | semmle.label | s2.unwrap_or(...) |
| main.rs:233:23:233:32 | source(...) | semmle.label | source(...) |
| main.rs:226:11:226:12 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:227:9:227:15 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:227:14:227:14 | n | semmle.label | n |
| main.rs:227:25:227:25 | n | semmle.label | n |
| main.rs:237:9:237:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:237:14:237:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:237:19:237:28 | source(...) | semmle.label | source(...) |
| main.rs:239:9:239:10 | i1 | semmle.label | i1 |
| main.rs:239:14:239:15 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:239:14:239:16 | TryExpr | semmle.label | TryExpr |
| main.rs:240:10:240:11 | i1 | semmle.label | i1 |
| main.rs:246:9:246:10 | s1 [Ok] | semmle.label | s1 [Ok] |
| main.rs:246:32:246:45 | Ok(...) [Ok] | semmle.label | Ok(...) [Ok] |
| main.rs:246:35:246:44 | source(...) | semmle.label | source(...) |
| main.rs:249:9:249:10 | i1 | semmle.label | i1 |
| main.rs:249:14:249:15 | s1 [Ok] | semmle.label | s1 [Ok] |
| main.rs:249:14:249:16 | TryExpr | semmle.label | TryExpr |
| main.rs:251:10:251:11 | i1 | semmle.label | i1 |
| main.rs:264:9:264:10 | s1 [A] | semmle.label | s1 [A] |
| main.rs:264:14:264:39 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
| main.rs:264:29:264:38 | source(...) | semmle.label | source(...) |
| main.rs:266:11:266:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:267:9:267:25 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
| main.rs:267:24:267:24 | n | semmle.label | n |
| main.rs:267:35:267:35 | n | semmle.label | n |
| main.rs:270:11:270:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:271:9:271:25 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
| main.rs:271:24:271:24 | n | semmle.label | n |
| main.rs:271:55:271:55 | n | semmle.label | n |
| main.rs:282:9:282:10 | s1 [A] | semmle.label | s1 [A] |
| main.rs:282:14:282:26 | A(...) [A] | semmle.label | A(...) [A] |
| main.rs:282:16:282:25 | source(...) | semmle.label | source(...) |
| main.rs:284:11:284:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:285:9:285:12 | A(...) [A] | semmle.label | A(...) [A] |
| main.rs:285:11:285:11 | n | semmle.label | n |
| main.rs:285:22:285:22 | n | semmle.label | n |
| main.rs:288:11:288:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:289:9:289:12 | A(...) [A] | semmle.label | A(...) [A] |
| main.rs:289:11:289:11 | n | semmle.label | n |
| main.rs:289:29:289:29 | n | semmle.label | n |
| main.rs:303:9:303:10 | s1 [C] | semmle.label | s1 [C] |
| main.rs:303:14:305:5 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:304:18:304:27 | source(...) | semmle.label | source(...) |
| main.rs:307:11:307:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:308:9:308:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:308:36:308:36 | n | semmle.label | n |
| main.rs:308:48:308:48 | n | semmle.label | n |
| main.rs:311:11:311:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:312:9:312:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:312:36:312:36 | n | semmle.label | n |
| main.rs:312:81:312:81 | n | semmle.label | n |
| main.rs:323:9:323:10 | s1 [C] | semmle.label | s1 [C] |
| main.rs:323:14:325:5 | C {...} [C] | semmle.label | C {...} [C] |
| main.rs:324:18:324:27 | source(...) | semmle.label | source(...) |
| main.rs:327:11:327:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:328:9:328:24 | C {...} [C] | semmle.label | C {...} [C] |
| main.rs:328:22:328:22 | n | semmle.label | n |
| main.rs:328:34:328:34 | n | semmle.label | n |
| main.rs:331:11:331:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:332:9:332:24 | C {...} [C] | semmle.label | C {...} [C] |
| main.rs:332:22:332:22 | n | semmle.label | n |
| main.rs:332:53:332:53 | n | semmle.label | n |
| main.rs:344:9:344:12 | arr1 [array[]] | semmle.label | arr1 [array[]] |
| main.rs:344:16:344:33 | [...] [array[]] | semmle.label | [...] [array[]] |
| main.rs:344:23:344:32 | source(...) | semmle.label | source(...) |
| main.rs:345:9:345:10 | n1 | semmle.label | n1 |
| main.rs:345:14:345:17 | arr1 [array[]] | semmle.label | arr1 [array[]] |
| main.rs:345:14:345:20 | arr1[2] | semmle.label | arr1[2] |
| main.rs:346:10:346:11 | n1 | semmle.label | n1 |
| main.rs:348:9:348:12 | arr2 [array[]] | semmle.label | arr2 [array[]] |
| main.rs:348:16:348:31 | [...; 10] [array[]] | semmle.label | [...; 10] [array[]] |
| main.rs:348:17:348:26 | source(...) | semmle.label | source(...) |
| main.rs:349:9:349:10 | n2 | semmle.label | n2 |
| main.rs:349:14:349:17 | arr2 [array[]] | semmle.label | arr2 [array[]] |
| main.rs:349:14:349:20 | arr2[4] | semmle.label | arr2[4] |
| main.rs:350:10:350:11 | n2 | semmle.label | n2 |
| main.rs:358:9:358:12 | arr1 [array[]] | semmle.label | arr1 [array[]] |
| main.rs:358:16:358:33 | [...] [array[]] | semmle.label | [...] [array[]] |
| main.rs:358:23:358:32 | source(...) | semmle.label | source(...) |
| main.rs:359:9:359:10 | n1 | semmle.label | n1 |
| main.rs:359:15:359:18 | arr1 [array[]] | semmle.label | arr1 [array[]] |
| main.rs:360:14:360:15 | n1 | semmle.label | n1 |
| main.rs:370:9:370:12 | arr1 [array[]] | semmle.label | arr1 [array[]] |
| main.rs:370:16:370:33 | [...] [array[]] | semmle.label | [...] [array[]] |
| main.rs:370:23:370:32 | source(...) | semmle.label | source(...) |
| main.rs:371:11:371:14 | arr1 [array[]] | semmle.label | arr1 [array[]] |
| main.rs:372:9:372:17 | SlicePat [array[]] | semmle.label | SlicePat [array[]] |
| main.rs:372:10:372:10 | a | semmle.label | a |
| main.rs:372:13:372:13 | b | semmle.label | b |
| main.rs:372:16:372:16 | c | semmle.label | c |
| main.rs:373:18:373:18 | a | semmle.label | a |
| main.rs:374:18:374:18 | b | semmle.label | b |
| main.rs:375:18:375:18 | c | semmle.label | c |
| main.rs:384:5:384:11 | [post] mut_arr [array[]] | semmle.label | [post] mut_arr [array[]] |
| main.rs:384:18:384:27 | source(...) | semmle.label | source(...) |
| main.rs:385:9:385:9 | d | semmle.label | d |
| main.rs:385:13:385:19 | mut_arr [array[]] | semmle.label | mut_arr [array[]] |
| main.rs:385:13:385:22 | mut_arr[1] | semmle.label | mut_arr[1] |
| main.rs:386:10:386:10 | d | semmle.label | d |
| main.rs:387:10:387:16 | mut_arr [array[]] | semmle.label | mut_arr [array[]] |
| main.rs:387:10:387:19 | mut_arr[0] | semmle.label | mut_arr[0] |
| main.rs:410:9:410:9 | s | semmle.label | s |
| main.rs:410:25:410:26 | source(...) | semmle.label | source(...) |
| main.rs:411:10:411:10 | s | semmle.label | s |
| main.rs:238:10:238:11 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:238:10:238:20 | s1.unwrap(...) | semmle.label | s1.unwrap(...) |
| main.rs:242:9:242:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:242:14:242:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:242:19:242:28 | source(...) | semmle.label | source(...) |
| main.rs:243:10:243:11 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:243:10:243:24 | s1.unwrap_or(...) | semmle.label | s1.unwrap_or(...) |
| main.rs:246:10:246:33 | s2.unwrap_or(...) | semmle.label | s2.unwrap_or(...) |
| main.rs:246:23:246:32 | source(...) | semmle.label | source(...) |
| main.rs:250:9:250:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:250:14:250:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:250:19:250:28 | source(...) | semmle.label | source(...) |
| main.rs:251:10:251:11 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:251:10:251:32 | s1.unwrap_or_else(...) | semmle.label | s1.unwrap_or_else(...) |
| main.rs:254:10:254:41 | s2.unwrap_or_else(...) | semmle.label | s2.unwrap_or_else(...) |
| main.rs:254:31:254:40 | source(...) | semmle.label | source(...) |
| main.rs:258:9:258:10 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:258:14:258:29 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:258:19:258:28 | source(...) | semmle.label | source(...) |
| main.rs:260:9:260:10 | i1 | semmle.label | i1 |
| main.rs:260:14:260:15 | s1 [Some] | semmle.label | s1 [Some] |
| main.rs:260:14:260:16 | TryExpr | semmle.label | TryExpr |
| main.rs:261:10:261:11 | i1 | semmle.label | i1 |
| main.rs:267:9:267:10 | s1 [Ok] | semmle.label | s1 [Ok] |
| main.rs:267:32:267:45 | Ok(...) [Ok] | semmle.label | Ok(...) [Ok] |
| main.rs:267:35:267:44 | source(...) | semmle.label | source(...) |
| main.rs:270:9:270:10 | i1 | semmle.label | i1 |
| main.rs:270:14:270:15 | s1 [Ok] | semmle.label | s1 [Ok] |
| main.rs:270:14:270:16 | TryExpr | semmle.label | TryExpr |
| main.rs:272:10:272:11 | i1 | semmle.label | i1 |
| main.rs:280:9:280:10 | s1 [Ok] | semmle.label | s1 [Ok] |
| main.rs:280:32:280:45 | Ok(...) [Ok] | semmle.label | Ok(...) [Ok] |
| main.rs:280:35:280:44 | source(...) | semmle.label | source(...) |
| main.rs:281:10:281:11 | s1 [Ok] | semmle.label | s1 [Ok] |
| main.rs:281:10:281:22 | s1.expect(...) | semmle.label | s1.expect(...) |
| main.rs:284:9:284:10 | s2 [Err] | semmle.label | s2 [Err] |
| main.rs:284:32:284:46 | Err(...) [Err] | semmle.label | Err(...) [Err] |
| main.rs:284:36:284:45 | source(...) | semmle.label | source(...) |
| main.rs:286:10:286:11 | s2 [Err] | semmle.label | s2 [Err] |
| main.rs:286:10:286:26 | s2.expect_err(...) | semmle.label | s2.expect_err(...) |
| main.rs:295:9:295:10 | s1 [A] | semmle.label | s1 [A] |
| main.rs:295:14:295:39 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
| main.rs:295:29:295:38 | source(...) | semmle.label | source(...) |
| main.rs:297:11:297:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:298:9:298:25 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
| main.rs:298:24:298:24 | n | semmle.label | n |
| main.rs:298:35:298:35 | n | semmle.label | n |
| main.rs:301:11:301:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:302:9:302:25 | ...::A(...) [A] | semmle.label | ...::A(...) [A] |
| main.rs:302:24:302:24 | n | semmle.label | n |
| main.rs:302:55:302:55 | n | semmle.label | n |
| main.rs:313:9:313:10 | s1 [A] | semmle.label | s1 [A] |
| main.rs:313:14:313:26 | A(...) [A] | semmle.label | A(...) [A] |
| main.rs:313:16:313:25 | source(...) | semmle.label | source(...) |
| main.rs:315:11:315:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:316:9:316:12 | A(...) [A] | semmle.label | A(...) [A] |
| main.rs:316:11:316:11 | n | semmle.label | n |
| main.rs:316:22:316:22 | n | semmle.label | n |
| main.rs:319:11:319:12 | s1 [A] | semmle.label | s1 [A] |
| main.rs:320:9:320:12 | A(...) [A] | semmle.label | A(...) [A] |
| main.rs:320:11:320:11 | n | semmle.label | n |
| main.rs:320:29:320:29 | n | semmle.label | n |
| main.rs:334:9:334:10 | s1 [C] | semmle.label | s1 [C] |
| main.rs:334:14:336:5 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:335:18:335:27 | source(...) | semmle.label | source(...) |
| main.rs:338:11:338:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:339:9:339:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:339:36:339:36 | n | semmle.label | n |
| main.rs:339:48:339:48 | n | semmle.label | n |
| main.rs:342:11:342:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:343:9:343:38 | ...::C {...} [C] | semmle.label | ...::C {...} [C] |
| main.rs:343:36:343:36 | n | semmle.label | n |
| main.rs:343:81:343:81 | n | semmle.label | n |
| main.rs:354:9:354:10 | s1 [C] | semmle.label | s1 [C] |
| main.rs:354:14:356:5 | C {...} [C] | semmle.label | C {...} [C] |
| main.rs:355:18:355:27 | source(...) | semmle.label | source(...) |
| main.rs:358:11:358:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:359:9:359:24 | C {...} [C] | semmle.label | C {...} [C] |
| main.rs:359:22:359:22 | n | semmle.label | n |
| main.rs:359:34:359:34 | n | semmle.label | n |
| main.rs:362:11:362:12 | s1 [C] | semmle.label | s1 [C] |
| main.rs:363:9:363:24 | C {...} [C] | semmle.label | C {...} [C] |
| main.rs:363:22:363:22 | n | semmle.label | n |
| main.rs:363:53:363:53 | n | semmle.label | n |
| main.rs:375:9:375:12 | arr1 [element] | semmle.label | arr1 [element] |
| main.rs:375:16:375:33 | [...] [element] | semmle.label | [...] [element] |
| main.rs:375:23:375:32 | source(...) | semmle.label | source(...) |
| main.rs:376:9:376:10 | n1 | semmle.label | n1 |
| main.rs:376:14:376:17 | arr1 [element] | semmle.label | arr1 [element] |
| main.rs:376:14:376:20 | arr1[2] | semmle.label | arr1[2] |
| main.rs:377:10:377:11 | n1 | semmle.label | n1 |
| main.rs:379:9:379:12 | arr2 [element] | semmle.label | arr2 [element] |
| main.rs:379:16:379:31 | [...; 10] [element] | semmle.label | [...; 10] [element] |
| main.rs:379:17:379:26 | source(...) | semmle.label | source(...) |
| main.rs:380:9:380:10 | n2 | semmle.label | n2 |
| main.rs:380:14:380:17 | arr2 [element] | semmle.label | arr2 [element] |
| main.rs:380:14:380:20 | arr2[4] | semmle.label | arr2[4] |
| main.rs:381:10:381:11 | n2 | semmle.label | n2 |
| main.rs:389:9:389:12 | arr1 [element] | semmle.label | arr1 [element] |
| main.rs:389:16:389:33 | [...] [element] | semmle.label | [...] [element] |
| main.rs:389:23:389:32 | source(...) | semmle.label | source(...) |
| main.rs:390:9:390:10 | n1 | semmle.label | n1 |
| main.rs:390:15:390:18 | arr1 [element] | semmle.label | arr1 [element] |
| main.rs:391:14:391:15 | n1 | semmle.label | n1 |
| main.rs:401:9:401:12 | arr1 [element] | semmle.label | arr1 [element] |
| main.rs:401:16:401:33 | [...] [element] | semmle.label | [...] [element] |
| main.rs:401:23:401:32 | source(...) | semmle.label | source(...) |
| main.rs:402:11:402:14 | arr1 [element] | semmle.label | arr1 [element] |
| main.rs:403:9:403:17 | SlicePat [element] | semmle.label | SlicePat [element] |
| main.rs:403:10:403:10 | a | semmle.label | a |
| main.rs:403:13:403:13 | b | semmle.label | b |
| main.rs:403:16:403:16 | c | semmle.label | c |
| main.rs:404:18:404:18 | a | semmle.label | a |
| main.rs:405:18:405:18 | b | semmle.label | b |
| main.rs:406:18:406:18 | c | semmle.label | c |
| main.rs:415:5:415:11 | [post] mut_arr [element] | semmle.label | [post] mut_arr [element] |
| main.rs:415:18:415:27 | source(...) | semmle.label | source(...) |
| main.rs:416:9:416:9 | d | semmle.label | d |
| main.rs:416:13:416:19 | mut_arr [element] | semmle.label | mut_arr [element] |
| main.rs:416:13:416:22 | mut_arr[1] | semmle.label | mut_arr[1] |
| main.rs:417:10:417:10 | d | semmle.label | d |
| main.rs:418:10:418:16 | mut_arr [element] | semmle.label | mut_arr [element] |
| main.rs:418:10:418:19 | mut_arr[0] | semmle.label | mut_arr[0] |
| main.rs:441:9:441:9 | s | semmle.label | s |
| main.rs:441:25:441:26 | source(...) | semmle.label | source(...) |
| main.rs:442:10:442:10 | s | semmle.label | s |
subpaths
testFailures
#select
@@ -350,27 +418,33 @@ testFailures
| main.rs:113:10:113:12 | a.0 | main.rs:111:11:111:20 | source(...) | main.rs:113:10:113:12 | a.0 | $@ | main.rs:111:11:111:20 | source(...) | source(...) |
| main.rs:121:10:121:15 | ... .1 | main.rs:118:17:118:26 | source(...) | main.rs:121:10:121:15 | ... .1 | $@ | main.rs:118:17:118:26 | source(...) | source(...) |
| main.rs:152:10:152:10 | a | main.rs:148:12:148:21 | source(...) | main.rs:152:10:152:10 | a | $@ | main.rs:148:12:148:21 | source(...) | source(...) |
| main.rs:201:33:201:33 | n | main.rs:198:27:198:36 | source(...) | main.rs:201:33:201:33 | n | $@ | main.rs:198:27:198:36 | source(...) | source(...) |
| main.rs:214:25:214:25 | n | main.rs:211:19:211:28 | source(...) | main.rs:214:25:214:25 | n | $@ | main.rs:211:19:211:28 | source(...) | source(...) |
| main.rs:225:10:225:20 | s1.unwrap(...) | main.rs:224:19:224:28 | source(...) | main.rs:225:10:225:20 | s1.unwrap(...) | $@ | main.rs:224:19:224:28 | source(...) | source(...) |
| main.rs:230:10:230:24 | s1.unwrap_or(...) | main.rs:229:19:229:28 | source(...) | main.rs:230:10:230:24 | s1.unwrap_or(...) | $@ | main.rs:229:19:229:28 | source(...) | source(...) |
| main.rs:233:10:233:33 | s2.unwrap_or(...) | main.rs:233:23:233:32 | source(...) | main.rs:233:10:233:33 | s2.unwrap_or(...) | $@ | main.rs:233:23:233:32 | source(...) | source(...) |
| main.rs:240:10:240:11 | i1 | main.rs:237:19:237:28 | source(...) | main.rs:240:10:240:11 | i1 | $@ | main.rs:237:19:237:28 | source(...) | source(...) |
| main.rs:251:10:251:11 | i1 | main.rs:246:35:246:44 | source(...) | main.rs:251:10:251:11 | i1 | $@ | main.rs:246:35:246:44 | source(...) | source(...) |
| main.rs:267:35:267:35 | n | main.rs:264:29:264:38 | source(...) | main.rs:267:35:267:35 | n | $@ | main.rs:264:29:264:38 | source(...) | source(...) |
| main.rs:271:55:271:55 | n | main.rs:264:29:264:38 | source(...) | main.rs:271:55:271:55 | n | $@ | main.rs:264:29:264:38 | source(...) | source(...) |
| main.rs:285:22:285:22 | n | main.rs:282:16:282:25 | source(...) | main.rs:285:22:285:22 | n | $@ | main.rs:282:16:282:25 | source(...) | source(...) |
| main.rs:289:29:289:29 | n | main.rs:282:16:282:25 | source(...) | main.rs:289:29:289:29 | n | $@ | main.rs:282:16:282:25 | source(...) | source(...) |
| main.rs:308:48:308:48 | n | main.rs:304:18:304:27 | source(...) | main.rs:308:48:308:48 | n | $@ | main.rs:304:18:304:27 | source(...) | source(...) |
| main.rs:312:81:312:81 | n | main.rs:304:18:304:27 | source(...) | main.rs:312:81:312:81 | n | $@ | main.rs:304:18:304:27 | source(...) | source(...) |
| main.rs:328:34:328:34 | n | main.rs:324:18:324:27 | source(...) | main.rs:328:34:328:34 | n | $@ | main.rs:324:18:324:27 | source(...) | source(...) |
| main.rs:332:53:332:53 | n | main.rs:324:18:324:27 | source(...) | main.rs:332:53:332:53 | n | $@ | main.rs:324:18:324:27 | source(...) | source(...) |
| main.rs:346:10:346:11 | n1 | main.rs:344:23:344:32 | source(...) | main.rs:346:10:346:11 | n1 | $@ | main.rs:344:23:344:32 | source(...) | source(...) |
| main.rs:350:10:350:11 | n2 | main.rs:348:17:348:26 | source(...) | main.rs:350:10:350:11 | n2 | $@ | main.rs:348:17:348:26 | source(...) | source(...) |
| main.rs:360:14:360:15 | n1 | main.rs:358:23:358:32 | source(...) | main.rs:360:14:360:15 | n1 | $@ | main.rs:358:23:358:32 | source(...) | source(...) |
| main.rs:373:18:373:18 | a | main.rs:370:23:370:32 | source(...) | main.rs:373:18:373:18 | a | $@ | main.rs:370:23:370:32 | source(...) | source(...) |
| main.rs:374:18:374:18 | b | main.rs:370:23:370:32 | source(...) | main.rs:374:18:374:18 | b | $@ | main.rs:370:23:370:32 | source(...) | source(...) |
| main.rs:375:18:375:18 | c | main.rs:370:23:370:32 | source(...) | main.rs:375:18:375:18 | c | $@ | main.rs:370:23:370:32 | source(...) | source(...) |
| main.rs:386:10:386:10 | d | main.rs:384:18:384:27 | source(...) | main.rs:386:10:386:10 | d | $@ | main.rs:384:18:384:27 | source(...) | source(...) |
| main.rs:387:10:387:19 | mut_arr[0] | main.rs:384:18:384:27 | source(...) | main.rs:387:10:387:19 | mut_arr[0] | $@ | main.rs:384:18:384:27 | source(...) | source(...) |
| main.rs:411:10:411:10 | s | main.rs:410:25:410:26 | source(...) | main.rs:411:10:411:10 | s | $@ | main.rs:410:25:410:26 | source(...) | source(...) |
| main.rs:186:18:186:18 | y | main.rs:175:13:175:22 | source(...) | main.rs:186:18:186:18 | y | $@ | main.rs:175:13:175:22 | source(...) | source(...) |
| main.rs:201:18:201:18 | x | main.rs:195:27:195:36 | source(...) | main.rs:201:18:201:18 | x | $@ | main.rs:195:27:195:36 | source(...) | source(...) |
| main.rs:214:33:214:33 | n | main.rs:211:27:211:36 | source(...) | main.rs:214:33:214:33 | n | $@ | main.rs:211:27:211:36 | source(...) | source(...) |
| main.rs:227:25:227:25 | n | main.rs:224:19:224:28 | source(...) | main.rs:227:25:227:25 | n | $@ | main.rs:224:19:224:28 | source(...) | source(...) |
| main.rs:238:10:238:20 | s1.unwrap(...) | main.rs:237:19:237:28 | source(...) | main.rs:238:10:238:20 | s1.unwrap(...) | $@ | main.rs:237:19:237:28 | source(...) | source(...) |
| main.rs:243:10:243:24 | s1.unwrap_or(...) | main.rs:242:19:242:28 | source(...) | main.rs:243:10:243:24 | s1.unwrap_or(...) | $@ | main.rs:242:19:242:28 | source(...) | source(...) |
| main.rs:246:10:246:33 | s2.unwrap_or(...) | main.rs:246:23:246:32 | source(...) | main.rs:246:10:246:33 | s2.unwrap_or(...) | $@ | main.rs:246:23:246:32 | source(...) | source(...) |
| main.rs:251:10:251:32 | s1.unwrap_or_else(...) | main.rs:250:19:250:28 | source(...) | main.rs:251:10:251:32 | s1.unwrap_or_else(...) | $@ | main.rs:250:19:250:28 | source(...) | source(...) |
| main.rs:254:10:254:41 | s2.unwrap_or_else(...) | main.rs:254:31:254:40 | source(...) | main.rs:254:10:254:41 | s2.unwrap_or_else(...) | $@ | main.rs:254:31:254:40 | source(...) | source(...) |
| main.rs:261:10:261:11 | i1 | main.rs:258:19:258:28 | source(...) | main.rs:261:10:261:11 | i1 | $@ | main.rs:258:19:258:28 | source(...) | source(...) |
| main.rs:272:10:272:11 | i1 | main.rs:267:35:267:44 | source(...) | main.rs:272:10:272:11 | i1 | $@ | main.rs:267:35:267:44 | source(...) | source(...) |
| main.rs:281:10:281:22 | s1.expect(...) | main.rs:280:35:280:44 | source(...) | main.rs:281:10:281:22 | s1.expect(...) | $@ | main.rs:280:35:280:44 | source(...) | source(...) |
| main.rs:286:10:286:26 | s2.expect_err(...) | main.rs:284:36:284:45 | source(...) | main.rs:286:10:286:26 | s2.expect_err(...) | $@ | main.rs:284:36:284:45 | source(...) | source(...) |
| main.rs:298:35:298:35 | n | main.rs:295:29:295:38 | source(...) | main.rs:298:35:298:35 | n | $@ | main.rs:295:29:295:38 | source(...) | source(...) |
| main.rs:302:55:302:55 | n | main.rs:295:29:295:38 | source(...) | main.rs:302:55:302:55 | n | $@ | main.rs:295:29:295:38 | source(...) | source(...) |
| main.rs:316:22:316:22 | n | main.rs:313:16:313:25 | source(...) | main.rs:316:22:316:22 | n | $@ | main.rs:313:16:313:25 | source(...) | source(...) |
| main.rs:320:29:320:29 | n | main.rs:313:16:313:25 | source(...) | main.rs:320:29:320:29 | n | $@ | main.rs:313:16:313:25 | source(...) | source(...) |
| main.rs:339:48:339:48 | n | main.rs:335:18:335:27 | source(...) | main.rs:339:48:339:48 | n | $@ | main.rs:335:18:335:27 | source(...) | source(...) |
| main.rs:343:81:343:81 | n | main.rs:335:18:335:27 | source(...) | main.rs:343:81:343:81 | n | $@ | main.rs:335:18:335:27 | source(...) | source(...) |
| main.rs:359:34:359:34 | n | main.rs:355:18:355:27 | source(...) | main.rs:359:34:359:34 | n | $@ | main.rs:355:18:355:27 | source(...) | source(...) |
| main.rs:363:53:363:53 | n | main.rs:355:18:355:27 | source(...) | main.rs:363:53:363:53 | n | $@ | main.rs:355:18:355:27 | source(...) | source(...) |
| main.rs:377:10:377:11 | n1 | main.rs:375:23:375:32 | source(...) | main.rs:377:10:377:11 | n1 | $@ | main.rs:375:23:375:32 | source(...) | source(...) |
| main.rs:381:10:381:11 | n2 | main.rs:379:17:379:26 | source(...) | main.rs:381:10:381:11 | n2 | $@ | main.rs:379:17:379:26 | source(...) | source(...) |
| main.rs:391:14:391:15 | n1 | main.rs:389:23:389:32 | source(...) | main.rs:391:14:391:15 | n1 | $@ | main.rs:389:23:389:32 | source(...) | source(...) |
| main.rs:404:18:404:18 | a | main.rs:401:23:401:32 | source(...) | main.rs:404:18:404:18 | a | $@ | main.rs:401:23:401:32 | source(...) | source(...) |
| main.rs:405:18:405:18 | b | main.rs:401:23:401:32 | source(...) | main.rs:405:18:405:18 | b | $@ | main.rs:401:23:401:32 | source(...) | source(...) |
| main.rs:406:18:406:18 | c | main.rs:401:23:401:32 | source(...) | main.rs:406:18:406:18 | c | $@ | main.rs:401:23:401:32 | source(...) | source(...) |
| main.rs:417:10:417:10 | d | main.rs:415:18:415:27 | source(...) | main.rs:417:10:417:10 | d | $@ | main.rs:415:18:415:27 | source(...) | source(...) |
| main.rs:418:10:418:19 | mut_arr[0] | main.rs:415:18:415:27 | source(...) | main.rs:418:10:418:19 | mut_arr[0] | $@ | main.rs:415:18:415:27 | source(...) | source(...) |
| main.rs:442:10:442:10 | s | main.rs:441:25:441:26 | source(...) | main.rs:442:10:442:10 | s | $@ | main.rs:441:25:441:26 | source(...) | source(...) |

View File

@@ -172,11 +172,9 @@ fn struct_nested_field() {
}
fn struct_nested_match() {
let y = source(93);
let p = Point3D {
plane: Point {
x: 2,
y: source(93),
},
plane: Point { x: 2, y },
z: 4,
};
match p {
@@ -185,12 +183,27 @@ fn struct_nested_match() {
z,
} => {
sink(x);
sink(y); // MISSING: hasValueFlow=93
sink(y); // $ hasValueFlow=93
sink(z);
}
}
}
struct MyTupleStruct(i64, i64);
fn tuple_struct() {
let s = MyTupleStruct(source(94), 2);
sink(s.0); // $ MISSING: hasValueFlow=94
sink(s.1);
match s {
MyTupleStruct(x, y) => {
sink(x); // $ hasValueFlow=94
sink(y);
}
}
}
// -----------------------------------------------------------------------------
// Data flow through enums
@@ -233,6 +246,14 @@ fn option_unwrap_or() {
sink(s2.unwrap_or(source(47))); // $ hasValueFlow=47
}
fn option_unwrap_or_else() {
let s1 = Some(source(47));
sink(s1.unwrap_or_else(|| 0)); // $ hasValueFlow=47
let s2 = None;
sink(s2.unwrap_or_else(|| source(48))); // $ hasValueFlow=48
}
fn option_questionmark() -> Option<i64> {
let s1 = Some(source(20));
let s2 = Some(2);
@@ -255,6 +276,16 @@ fn result_questionmark() -> Result<i64, i64> {
Ok(0)
}
fn result_expect() {
let s1: Result<i64, i64> = Ok(source(78));
sink(s1.expect("")); // $ hasValueFlow=78
sink(s1.expect_err(""));
let s2: Result<i64, i64> = Err(source(79));
sink(s2.expect(""));
sink(s2.expect_err("")); // $ hasValueFlow=79
}
enum MyTupleEnum {
A(i64),
B(i64),
@@ -390,14 +421,14 @@ fn array_assignment() {
// Test data flow inconsistency occuring with captured variables and `continue`
// in a loop.
pub fn captured_variable_and_continue(names: Vec<(bool, Option<String>)>) {
let default_name = source(83).to_string();
for (cond, name) in names {
if cond {
let n = name.unwrap_or_else(|| default_name.to_string());
sink(n.len() as i64);
continue;
let default_name = source(83).to_string();
for (cond, name) in names {
if cond {
let n = name.unwrap_or_else(|| default_name.to_string());
sink(n.len() as i64);
continue;
}
}
}
}
macro_rules! get_source {
@@ -424,6 +455,7 @@ fn main() {
tuple_mutation();
tuple_nested();
struct_field();
tuple_struct();
struct_mutation();
struct_pattern_match();
struct_nested_field();

View File

@@ -0,0 +1,94 @@
models
| 1 | Summary: lang:core; <crate::option::Option>::unwrap; Argument[self].Variant[crate::option::Option::Some(0)]; ReturnValue; value |
| 2 | Summary: lang:core; <crate::result::Result>::unwrap; Argument[self].Variant[crate::result::Result::Ok(0)]; ReturnValue; value |
edges
| main.rs:13:9:13:9 | a [Some] | main.rs:14:10:14:10 | a [Some] | provenance | |
| main.rs:13:9:13:9 | a [Some] | main.rs:15:13:15:13 | a [Some] | provenance | |
| main.rs:13:13:13:28 | Some(...) [Some] | main.rs:13:9:13:9 | a [Some] | provenance | |
| main.rs:13:18:13:27 | source(...) | main.rs:13:13:13:28 | Some(...) [Some] | provenance | |
| main.rs:14:10:14:10 | a [Some] | main.rs:14:10:14:19 | a.unwrap(...) | provenance | MaD:1 |
| main.rs:15:9:15:9 | b [Some] | main.rs:16:10:16:10 | b [Some] | provenance | |
| main.rs:15:13:15:13 | a [Some] | main.rs:15:13:15:21 | a.clone(...) [Some] | provenance | |
| main.rs:15:13:15:21 | a.clone(...) [Some] | main.rs:15:9:15:9 | b [Some] | provenance | |
| main.rs:16:10:16:10 | b [Some] | main.rs:16:10:16:19 | b.unwrap(...) | provenance | MaD:1 |
| main.rs:20:9:20:9 | a [Ok] | main.rs:21:10:21:10 | a [Ok] | provenance | |
| main.rs:20:9:20:9 | a [Ok] | main.rs:22:13:22:13 | a [Ok] | provenance | |
| main.rs:20:31:20:44 | Ok(...) [Ok] | main.rs:20:9:20:9 | a [Ok] | provenance | |
| main.rs:20:34:20:43 | source(...) | main.rs:20:31:20:44 | Ok(...) [Ok] | provenance | |
| main.rs:21:10:21:10 | a [Ok] | main.rs:21:10:21:19 | a.unwrap(...) | provenance | MaD:2 |
| main.rs:22:9:22:9 | b [Ok] | main.rs:23:10:23:10 | b [Ok] | provenance | |
| main.rs:22:13:22:13 | a [Ok] | main.rs:22:13:22:21 | a.clone(...) [Ok] | provenance | |
| main.rs:22:13:22:21 | a.clone(...) [Ok] | main.rs:22:9:22:9 | b [Ok] | provenance | |
| main.rs:23:10:23:10 | b [Ok] | main.rs:23:10:23:19 | b.unwrap(...) | provenance | MaD:2 |
| main.rs:27:9:27:9 | a | main.rs:28:10:28:10 | a | provenance | |
| main.rs:27:9:27:9 | a | main.rs:29:13:29:13 | a | provenance | |
| main.rs:27:13:27:22 | source(...) | main.rs:27:9:27:9 | a | provenance | |
| main.rs:29:9:29:9 | b | main.rs:30:10:30:10 | b | provenance | |
| main.rs:29:13:29:13 | a | main.rs:29:13:29:21 | a.clone(...) | provenance | |
| main.rs:29:13:29:21 | a.clone(...) | main.rs:29:9:29:9 | b | provenance | |
| main.rs:42:13:42:13 | w [Wrapper] | main.rs:43:15:43:15 | w [Wrapper] | provenance | |
| main.rs:42:17:42:41 | Wrapper {...} [Wrapper] | main.rs:42:13:42:13 | w [Wrapper] | provenance | |
| main.rs:42:30:42:39 | source(...) | main.rs:42:17:42:41 | Wrapper {...} [Wrapper] | provenance | |
| main.rs:43:15:43:15 | w [Wrapper] | main.rs:44:13:44:28 | Wrapper {...} [Wrapper] | provenance | |
| main.rs:43:15:43:15 | w [Wrapper] | main.rs:46:17:46:17 | w [Wrapper] | provenance | |
| main.rs:44:13:44:28 | Wrapper {...} [Wrapper] | main.rs:44:26:44:26 | n | provenance | |
| main.rs:44:26:44:26 | n | main.rs:44:38:44:38 | n | provenance | |
| main.rs:46:13:46:13 | u [Wrapper] | main.rs:47:15:47:15 | u [Wrapper] | provenance | |
| main.rs:46:17:46:17 | w [Wrapper] | main.rs:46:17:46:25 | w.clone(...) [Wrapper] | provenance | |
| main.rs:46:17:46:25 | w.clone(...) [Wrapper] | main.rs:46:13:46:13 | u [Wrapper] | provenance | |
| main.rs:47:15:47:15 | u [Wrapper] | main.rs:48:13:48:28 | Wrapper {...} [Wrapper] | provenance | |
| main.rs:48:13:48:28 | Wrapper {...} [Wrapper] | main.rs:48:26:48:26 | n | provenance | |
| main.rs:48:26:48:26 | n | main.rs:48:38:48:38 | n | provenance | |
nodes
| main.rs:13:9:13:9 | a [Some] | semmle.label | a [Some] |
| main.rs:13:13:13:28 | Some(...) [Some] | semmle.label | Some(...) [Some] |
| main.rs:13:18:13:27 | source(...) | semmle.label | source(...) |
| main.rs:14:10:14:10 | a [Some] | semmle.label | a [Some] |
| main.rs:14:10:14:19 | a.unwrap(...) | semmle.label | a.unwrap(...) |
| main.rs:15:9:15:9 | b [Some] | semmle.label | b [Some] |
| main.rs:15:13:15:13 | a [Some] | semmle.label | a [Some] |
| main.rs:15:13:15:21 | a.clone(...) [Some] | semmle.label | a.clone(...) [Some] |
| main.rs:16:10:16:10 | b [Some] | semmle.label | b [Some] |
| main.rs:16:10:16:19 | b.unwrap(...) | semmle.label | b.unwrap(...) |
| main.rs:20:9:20:9 | a [Ok] | semmle.label | a [Ok] |
| main.rs:20:31:20:44 | Ok(...) [Ok] | semmle.label | Ok(...) [Ok] |
| main.rs:20:34:20:43 | source(...) | semmle.label | source(...) |
| main.rs:21:10:21:10 | a [Ok] | semmle.label | a [Ok] |
| main.rs:21:10:21:19 | a.unwrap(...) | semmle.label | a.unwrap(...) |
| main.rs:22:9:22:9 | b [Ok] | semmle.label | b [Ok] |
| main.rs:22:13:22:13 | a [Ok] | semmle.label | a [Ok] |
| main.rs:22:13:22:21 | a.clone(...) [Ok] | semmle.label | a.clone(...) [Ok] |
| main.rs:23:10:23:10 | b [Ok] | semmle.label | b [Ok] |
| main.rs:23:10:23:19 | b.unwrap(...) | semmle.label | b.unwrap(...) |
| main.rs:27:9:27:9 | a | semmle.label | a |
| main.rs:27:13:27:22 | source(...) | semmle.label | source(...) |
| main.rs:28:10:28:10 | a | semmle.label | a |
| main.rs:29:9:29:9 | b | semmle.label | b |
| main.rs:29:13:29:13 | a | semmle.label | a |
| main.rs:29:13:29:21 | a.clone(...) | semmle.label | a.clone(...) |
| main.rs:30:10:30:10 | b | semmle.label | b |
| main.rs:42:13:42:13 | w [Wrapper] | semmle.label | w [Wrapper] |
| main.rs:42:17:42:41 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] |
| main.rs:42:30:42:39 | source(...) | semmle.label | source(...) |
| main.rs:43:15:43:15 | w [Wrapper] | semmle.label | w [Wrapper] |
| main.rs:44:13:44:28 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] |
| main.rs:44:26:44:26 | n | semmle.label | n |
| main.rs:44:38:44:38 | n | semmle.label | n |
| main.rs:46:13:46:13 | u [Wrapper] | semmle.label | u [Wrapper] |
| main.rs:46:17:46:17 | w [Wrapper] | semmle.label | w [Wrapper] |
| main.rs:46:17:46:25 | w.clone(...) [Wrapper] | semmle.label | w.clone(...) [Wrapper] |
| main.rs:47:15:47:15 | u [Wrapper] | semmle.label | u [Wrapper] |
| main.rs:48:13:48:28 | Wrapper {...} [Wrapper] | semmle.label | Wrapper {...} [Wrapper] |
| main.rs:48:26:48:26 | n | semmle.label | n |
| main.rs:48:38:48:38 | n | semmle.label | n |
subpaths
testFailures
#select
| main.rs:14:10:14:19 | a.unwrap(...) | main.rs:13:18:13:27 | source(...) | main.rs:14:10:14:19 | a.unwrap(...) | $@ | main.rs:13:18:13:27 | source(...) | source(...) |
| main.rs:16:10:16:19 | b.unwrap(...) | main.rs:13:18:13:27 | source(...) | main.rs:16:10:16:19 | b.unwrap(...) | $@ | main.rs:13:18:13:27 | source(...) | source(...) |
| main.rs:21:10:21:19 | a.unwrap(...) | main.rs:20:34:20:43 | source(...) | main.rs:21:10:21:19 | a.unwrap(...) | $@ | main.rs:20:34:20:43 | source(...) | source(...) |
| main.rs:23:10:23:19 | b.unwrap(...) | main.rs:20:34:20:43 | source(...) | main.rs:23:10:23:19 | b.unwrap(...) | $@ | main.rs:20:34:20:43 | source(...) | source(...) |
| main.rs:28:10:28:10 | a | main.rs:27:13:27:22 | source(...) | main.rs:28:10:28:10 | a | $@ | main.rs:27:13:27:22 | source(...) | source(...) |
| main.rs:30:10:30:10 | b | main.rs:27:13:27:22 | source(...) | main.rs:30:10:30:10 | b | $@ | main.rs:27:13:27:22 | source(...) | source(...) |
| main.rs:44:38:44:38 | n | main.rs:42:30:42:39 | source(...) | main.rs:44:38:44:38 | n | $@ | main.rs:42:30:42:39 | source(...) | source(...) |
| main.rs:48:38:48:38 | n | main.rs:42:30:42:39 | source(...) | main.rs:48:38:48:38 | n | $@ | main.rs:42:30:42:39 | source(...) | source(...) |

View File

@@ -0,0 +1,12 @@
/**
* @kind path-problem
*/
import rust
import utils.test.InlineFlowTest
import DefaultFlowTest
import ValueFlow::PathGraph
from ValueFlow::PathNode source, ValueFlow::PathNode sink
where ValueFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()

View File

@@ -0,0 +1,58 @@
fn source(i: i64) -> i64 {
1000 + i
}
fn sink(s: i64) {
println!("{}", s);
}
// Flow through `clone` methods
fn option_clone() {
let a = Some(source(88));
sink(a.unwrap()); // $ hasValueFlow=88
let b = a.clone();
sink(b.unwrap()); // $ hasValueFlow=88
}
fn result_clone() {
let a: Result<i64, i64> = Ok(source(37));
sink(a.unwrap()); // $ hasValueFlow=37
let b = a.clone();
sink(b.unwrap()); // $ hasValueFlow=37
}
fn i64_clone() {
let a = source(12);
sink(a); // $ hasValueFlow=12
let b = a.clone();
sink(b); // $ hasValueFlow=12
}
mod my_clone {
use super::{source, sink};
#[derive(Clone)]
struct Wrapper {
n: i64
}
pub fn wrapper_clone() {
let w = Wrapper { n: source(73) };
match w {
Wrapper { n: n } => sink(n) // $ hasValueFlow=73
}
let u = w.clone();
match u {
Wrapper { n: n } => sink(n) // $ hasValueFlow=73
}
}
}
fn main() {
option_clone();
result_clone();
i64_clone();
my_clone::wrapper_clone();
}

Some files were not shown because too many files have changed in this diff Show More