歡迎來到 黑吧安全網 聚焦網絡安全前沿資訊,精華內容,交流技術心得!

代碼分析平臺CodeQL學習手記(五)

來源:本站整理 作者:佚名 時間:2020-01-22 TAG: 我要投稿

在前面的文章中,我們通過一個有趣的例子來介紹了邏輯謂詞的用法。在本文中,隨著破案故事的推進,我們將進一步學習邏輯連接詞和聚合操作的運用。
邏輯連接詞
在之前搜集的破案線索中,有些問題的答案是肯定的,例如“小偷身高超過150厘米嗎?”的答案為“是”。為了利用這種類型的信息,我們可以編寫如下所示的查詢,來找出所有身高超過150厘米的村民。這些人都是我們的懷疑對象。
from Person t
where t.getHeight() > 150
select t
在利用其他線索編寫相應的查詢之前,我們需要先來熟悉另一個有用的工具:邏輯連接詞。
借助于邏輯連接詞,我們可以組合不同的信息或判斷,從而編寫出更加復雜的查詢。例如,如果知道小偷的年齡超過30歲并且頭發是棕色的,就可以使用下面的 where 子句來連接兩個謂詞:
where t.getAge() > 30 and t.getHairColor() = "brown"
需要注意的是,由于謂詞getHairColor()返回的是一個字符串,因此,我們需要用引號將單詞brown括起來。
如果小偷不住在城堡的北邊,可以用下面的語句進行描述:
where not t.getLocation() = "north"
如果小偷頭發顏色為棕色或黑色,可以用下面的語句進行描述:
where t.getHairColor() = "brown" or t.getHairColor() = "black"
下面,我們通過連接詞來將上面的語句連成一句:
where t.getAge() > 30
  and (t.getHairColor() = "brown" or t.getHairColor() = "black")
  and not t.getLocation() = "north"
需要注意的是,我們在 or 子句的前后使用了一對圓括號,以使查詢符合預期。如果沒有括號的話,由于連接詞and的優先級別高于連接詞or,所以,實際上就會變成:
where (t.getAge() > 30 and t.getHairColor() = "brown")
  or (t.getHairColor() = "black" and not t.getLocation() = "north")
此外,如果一個人 p 的頭發正在由黑變灰,那么可以用p.getHairColor() = "black" andp.getHairColor() = "gray"來表示。如果小偷是禿頭怎么辦?在這種情況下,小偷沒有頭發,因此,謂詞getHairColor()就不應返回任何結果!
如果我們知道小偷肯定不是禿頭,那么這時有一點可以肯定:必然有一種顏色與小偷的頭發顏色相匹配。這時,可以引入一個字符串類型的新變量 c,并找出頭發顏色,即t.getaircolor()返回結果與變量c 的值相匹配的那些人。
from Person t, string c
where t.getHairColor() = c
select t
注意,這里的變量c只是臨時使用一下,在select子句中根本就沒有用到它。在這種情況下,最好使用exists,具體如下所示:
from Person t
where exists(string c | t.getHairColor() = c)
select t
在這里,exists引入了一個字符串類型的臨時變量 c,并且僅在至少有一個字符串c滿足條件 t.getHairColor() = c時,這個where子句才成立。
注意:QL語言中exists對應于邏輯學中的存在量詞,表示“存在某個”或“至少有一個”。 此外,QL語言中還提供了一個通用量詞,即forall,表示“所有的”,或“每一個”。
從線索到查詢
現在,我們已經為追查小偷做好了充分的準備了。接下來,我們將編寫一個查詢,找出符合前8個線索的村民,這些線索包括:

首先,一定不要忘了導入tutorial,具體如下所示:
import tutoria
然后,聲明一個表示村民的變量:
from Person t
接下來,我們分別將上面的每條線索翻譯成相應的QL語句即可。其中,對于問題1,可以翻譯為如下所示的語句:
t.getHeight() > 150
對于問題2,可以翻譯為如下所示的語句:
not t.getHairColor() = "blond"
對于問題3,我們知道禿子是沒有頭發的,那么也就無所謂發色了。換句話說,如果查詢某人,返回了頭發的顏色,那么,說明這個人肯定不是禿子。所以,這個線索等價于下面的語句:
exists (string c | t.getHairColor() = c)
對于問題4,可以翻譯為如下所示的語句:
not t.getAge()
對于問題5,可以翻譯為如下所示的語句:
t.getLocation() = "east"
對于問題6,可以翻譯為如下所示的語句:
(t.getHairColor() = "black" or t.getHairColor() = "brown")
注意,考慮到邏輯連接詞的優先級問題,為了符合預期,這里需要使用圓括號。對于問題7,可以翻譯為如下所示的語句:
not (t.getHeight() > 180 and t.getHeight()
同樣,為了符合預期,這里也用到了圓括號。對于問題8,如果一個人不是最老的,那么至少有一個人比他/她年齡大,因此,可以將其變成判斷存在性的問題:
exists(Person p | p.getAge() > t.getAge())
最后,我們使用邏輯連接詞and將這些條件組合起來,也就是這些條件必須全部滿足:

這樣,我們就能得到一個嫌疑人列表,小偷就在這個范圍內:

注意,上面代碼使用了注釋符/* 和*/,其中,位于/* 和*/之間的文本都不會作為 QL 代碼進行處理,而是作為提示內容供我們人類“看的”。
現在,雖然我們已經排除了一部分人,但是,我們的嫌疑人名單還是很長。為了找出小偷,我們還必須收集更多的信息,以進一步改善我們的查詢。
聚合操作
當我們需要找出村子里最老、最年輕、最高、最矮的人的時候,除了使用 exists間接完成之外,還有一種更有效的方法,那就是使用聚合函數,例如max和min函數等。

[1] [2]  下一頁

【聲明】:黑吧安全網(http://www.zjtpzs.live)登載此文出于傳遞更多信息之目的,并不代表本站贊同其觀點和對其真實性負責,僅適于網絡安全技術愛好者學習研究使用,學習中請遵循國家相關法律法規。如有問題請聯系我們,聯系郵箱[email protected],我們會在最短的時間內進行處理。
  • 最新更新
    • 相關閱讀
      • 本類熱門
        • 最近下載
        神秘东方电子游艺 棒球比分怎么看 四川宜宾麻将下载 河北十一选五历史遗 福建十一选五走势图 激情黄色片段 好运彩网站登录 用麻将玩的其他小游戏 山东十一选五幸运之门 江苏十一选五开奖公 欧美av明星qq群 广东26选5中奖规则 宁夏十一选五 网上捕鱼平台 有那些网上棋牌 麻将赢家36招 福州全民麻将下载