簡體   English   中英

短路評估是否可以觸發競爭條件?

[英]Can short-circuit evaluation trigger a race condition?

我喜歡打高爾夫球。 鑒於CVE-2016-5195 ,我想知道我的任何“ golf”代碼是否都可以觸發競爭條件。

假設我們有兩個函數,兩個函數都返回一個布爾值,並且我們正在初始化一個名為result的布爾變量:

result = foo() || bar();

在理想的世界中,我們有兩種情況:

  1. foo返回true 不要打電話bar result等於true [短路情況]
  2. foo返回false 致電bar() result等於bar返回的值。

我的問題是:是否會有一段時間違反短路評估,並且盡管foo返回true foo調用bar ,或更糟糕的是,可能是由於多線程而在foo被調用之前先調用bar嗎? 如果是這樣,您是否可以提供一段代碼來觸發這種行為?

您的答案可能是關於使用該語法有效的任何一種或多種語言的,盡管我認為某些語言對這種語言的要求會比其他語言更為嚴格。

當一系列操作的結果取決於執行這些操作的順序時,就會發生競爭條件。

&&|| C ++中的運算符保證從左到右求值,並且如果第一個運算符為false / true則不對第二個運算符進行求值。 由於操作順序是有保證的,因此foo操作和bar操作之間沒有競爭條件。 但是,每個操作之間仍然存在競爭條件。

違反上述保證的代碼不是C ++代碼,同樣,符合要求的C ++編譯器也永遠不會發出違反那些保證的代碼。

您所指的情況不是競爭條件。 讓我們再次回到您的問題:

是否會有一段時間違反短路評估,盡管foo返回true仍會調用bar,或者更糟糕的是,可能由於多線程而在調用foo之前先調用bar嗎?

我猜正確的問題是:

將永遠是一個有酒吧時被調用調用函數foo使用假的結果的時間,但同時它被稱為foo將返回true,如果將被再次叫什么名字?

好的,讓我們用潛在的race condition狀態編寫一些代碼。

#define BUFFER_SIZE 0x1000
char globalBuffer[BUFFER_SIZE];

bool foo() { // have user an access to the path_to_file file?
   return access(path_to_file, 0666) != 0; // path_to_file declared somewhere
}

bool bar() {
    FILE *file = fopen(path_to_file, "r");
    if (file == NULL) return false;
    char *ptr = gfets(globalBuffer, BUFFER_SIZE, file);
    if (ptr == NULL) return false;
    return true;
}
...
result = foo() || bar(); // if foo is false, then user have an access
printf("%s", globalBuffer);

假設我們可以控制path_to_file。

如果我們像這樣做一個無限循環,就會出現競爭條件

#!/bin/bash

while :
do
    ln -s /path/to/good/access/file /path/to/file
    rm -f /path/to/file
    ln -s /etc/shadow /path/to/file
done

經過一些嘗試,如果您的應用程序具有suid位-我將讀取/ etc / shadow的內容

但是,讓我們回到您的問題:

不行不行 如果foo返回true,則不會調用bar 即使您來自其他線程,如果您有多線程。 每個線程都有自己的寄存器和堆棧。 因此,在同一個表達式中調用兩個函數的情況下,您應該相信c ++標准。 但這並不意味着您的代碼是安全的。 種族狀況是100種可能出現的問題之一。

請注意,C ++支持運算符重載,但短路僅是內置運算符(c ++ 17之前)的功能,而不是用戶提供的重載。

也就是說,在所有當前版本的C ++中,除非您同時知道這兩種類型並且知道沒有自由函數運算符,否則不能假定會發生短路。 正在陰影中。

有關p0145的信息 ,請參見c ++ 17中的變化。

(粗體是加法,斜體去除)

更改第5/2段,如下所示:[注意:運算符可以重載,即在應用於類類型(條款9)或枚舉類型(7.2)的表達式時具有特定含義。 重載運算符的使用將轉換為函數調用,如13.5中所述。 重載的運算符遵循第5章中指定的語法和評估順序規則,但操作數類型*,* 值類別以及評估順序的要求已由函數調用規則取代。 對於重載的運算符(13.5),不能保證運算符之間的關系(例如++ a表示a + = 1),對於布爾類型的操作數也不保證。 —尾注]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM