mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
Merge branch 'main' into rust-rusqlite
This commit is contained in:
17
rust/ql/.generated.list
generated
17
rust/ql/.generated.list
generated
@@ -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
3
rust/ql/.gitattributes
generated
vendored
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.1.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
rust/ql/lib/change-notes/released/0.1.1.md
Normal file
3
rust/ql/lib/change-notes/released/0.1.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.1.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.1.0
|
||||
lastReleaseVersion: 0.1.1
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
|
||||
private import codeql.rust.frameworks.rustcrypto.RustCrypto
|
||||
private import codeql.rust.frameworks.Sqlx
|
||||
private import codeql.rust.frameworks.stdlib.Clone
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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() }
|
||||
}
|
||||
|
||||
5
rust/ql/lib/codeql/rust/elements/UseTree.qll
generated
5
rust/ql/lib/codeql/rust/elements/UseTree.qll
generated
@@ -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;
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
472
rust/ql/lib/codeql/rust/elements/internal/PathResolution.qll
Normal file
472
rust/ql/lib/codeql/rust/elements/internal/PathResolution.qll
Normal 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 != "_"
|
||||
)
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
17
rust/ql/lib/codeql/rust/frameworks/log.model.yml
Normal file
17
rust/ql/lib/codeql/rust/frameworks/log.model.yml
Normal 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"]
|
||||
@@ -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"]
|
||||
|
||||
@@ -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()
|
||||
|
||||
21
rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll
Normal file
21
rust/ql/lib/codeql/rust/frameworks/stdlib/Clone.qll
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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%")) }
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
21
rust/ql/lib/utils/test/InlineMadTest.qll
Normal file
21
rust/ql/lib/utils/test/InlineMadTest.qll
Normal 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>
|
||||
9
rust/ql/lib/utils/test/TranslateModels.qll
Normal file
9
rust/ql/lib/utils/test/TranslateModels.qll
Normal 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>
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
## 0.1.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.1.0
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
3
rust/ql/src/change-notes/released/0.1.1.md
Normal file
3
rust/ql/src/change-notes/released/0.1.1.md
Normal file
@@ -0,0 +1,3 @@
|
||||
## 0.1.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.1.0
|
||||
lastReleaseVersion: 0.1.1
|
||||
|
||||
1
rust/ql/src/codeql-suites/rust-ccr.qls
Normal file
1
rust/ql/src/codeql-suites/rust-ccr.qls
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/rust-queries
|
||||
version: 0.1.1-dev
|
||||
version: 0.1.2-dev
|
||||
groups:
|
||||
- rust
|
||||
- queries
|
||||
|
||||
38
rust/ql/src/queries/security/CWE-312/CleartextLogging.qhelp
Normal file
38
rust/ql/src/queries/security/CWE-312/CleartextLogging.qhelp
Normal 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>
|
||||
58
rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
Normal file
58
rust/ql/src/queries/security/CWE-312/CleartextLogging.ql
Normal 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()
|
||||
@@ -0,0 +1,2 @@
|
||||
let password = "P@ssw0rd";
|
||||
info!("User password changed to {password}");
|
||||
@@ -0,0 +1,2 @@
|
||||
let password = "P@ssw0rd";
|
||||
info!("User password changed");
|
||||
@@ -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"]
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
13
rust/ql/src/utils/modelgenerator/CaptureNeutralModels.ql
Normal file
13
rust/ql/src/utils/modelgenerator/CaptureNeutralModels.ql
Normal 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
|
||||
13
rust/ql/src/utils/modelgenerator/CaptureSinkModels.ql
Normal file
13
rust/ql/src/utils/modelgenerator/CaptureSinkModels.ql
Normal 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
|
||||
13
rust/ql/src/utils/modelgenerator/CaptureSourceModels.ql
Normal file
13
rust/ql/src/utils/modelgenerator/CaptureSourceModels.ql
Normal 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
|
||||
13
rust/ql/src/utils/modelgenerator/CaptureSummaryModels.ql
Normal file
13
rust/ql/src/utils/modelgenerator/CaptureSummaryModels.ql
Normal 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
|
||||
15
rust/ql/src/utils/modelgenerator/GenerateFlowModel.py
Normal file
15
rust/ql/src/utils/modelgenerator/GenerateFlowModel.py
Normal 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()
|
||||
@@ -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"
|
||||
@@ -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"
|
||||
1
rust/ql/src/utils/modelgenerator/debug/README.md
Normal file
1
rust/ql/src/utils/modelgenerator/debug/README.md
Normal file
@@ -0,0 +1 @@
|
||||
The queries in this directory are purely used for model generator debugging purposes in VS Code.
|
||||
185
rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll
Normal file
185
rust/ql/src/utils/modelgenerator/internal/CaptureModels.qll
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| gen_use_tree.rs:7:9:7:46 | UseTree | gen_use_tree.rs:7:35:7:46 | Rename |
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| gen_use_tree.rs:8:9:8:50 | UseTree | gen_use_tree.rs:8:27:8:50 | UseTreeList |
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
|
||||
1964
rust/ql/test/library-tests/controlflow/BasicBlocks.expected
Normal file
1964
rust/ql/test/library-tests/controlflow/BasicBlocks.expected
Normal file
File diff suppressed because it is too large
Load Diff
23
rust/ql/test/library-tests/controlflow/BasicBlocks.ql
Normal file
23
rust/ql/test/library-tests/controlflow/BasicBlocks.ql
Normal 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
@@ -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,
|
||||
|
||||
@@ -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(...) |
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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(...) |
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(...) |
|
||||
12
rust/ql/test/library-tests/dataflow/modeled/inline-flow.ql
Normal file
12
rust/ql/test/library-tests/dataflow/modeled/inline-flow.ql
Normal 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()
|
||||
58
rust/ql/test/library-tests/dataflow/modeled/main.rs
Normal file
58
rust/ql/test/library-tests/dataflow/modeled/main.rs
Normal 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
Reference in New Issue
Block a user