2012-02-14 76 views
0

我們正在將基於C++ openssl的項目轉換爲python w/M2Crypto,並且我們遇到了一個與M2Crypto的BIO例程有點不同的問題。具體而言,對BIO.readlines()的任何調用都會永久掛在文件對象上。M2Crypto BIO.readlines掛起,python 2.7

下面是什麼,我們嘗試了快速出樣:

f = open('test.txt','w') 
f.write('hello world\n') 
f.close() 

import M2Crypto.BIO 
bio = M2Crypto.BIO.openfile('test.txt','r') 
lines = bio.readlines() 
# the above call hangs forever 

爲了確保我們沒有什麼可怕的錯誤與我們的OpenSSL安裝,我們創建一個小的測試程序來讀取test.txt文件我們只創建

#include <openssl/bio.h> 
#include <openssl/err.h> 
int main() { 
    const int maxrd = 4096; 
    char line[maxrd]; 
    int rd; 
    BIO* bio = BIO_new_file("test.txt","r"); 
    while((rd = BIO_gets(bio, line, maxrd)) > 0) { 
     printf("%s",line); 
     } 
    if (rd == -1) { 
     printf("BIO error %ld\n", ERR_get_error()); 
     } 
    } 

沒問題。

我們一直在研究M2Crypto-0.21.1/SWIG/_bio.i包裝文件,並認爲我們可能有問題的根源。 109線路測試從BIO_gets()的返回值

if (r < 0) { 
    // return Py_None 
    } 

,但對於BIO_gets手冊頁()表明,它可能會返回0或-1表示結束流。

我相信它應該是

if (r < 1) { 
    // return Py_None 
    } 

但想看看是否遇到過其他的 - 或者我們是否在我們的BIO_gets的理解()系統錯誤的。

--- ---詳細 Pythong 2.7 M2Crypto 0.21.1 OpenSSL的0.9.8q-FIPS 2010年12月2日 的FreeBSD 8.2-RELEASE-P4

回答

0

在其他情況下,未來整個中國原創,我想分享我們的補丁。

--- M2Crypto-0.21.1.orig/SWIG/_bio.i 2011-01-15 14:10:06.000000000 -0500 
+++ M2Crypto-0.21.1/SWIG/_bio.i 2012-02-14 11:34:15.000000000 -0500 
@@ -106,7 +106,7 @@ 
    Py_BEGIN_ALLOW_THREADS 
    r = BIO_gets(bio, buf, num); 
    Py_END_ALLOW_THREADS 
- if (r < 0) { 
+ if (r < 1) { 
     PyMem_Free(buf); 
     if (ERR_peek_error()) { 
      PyErr_SetString(_bio_err, ERR_reason_error_string(ERR_get_error())); 

注:對於那些熟悉M2Crypto的內部,有三個基本解決這個問題。第一個是上面發佈的補丁。既然我們相信這符合BIO_gets()的手冊頁的意圖,那就是我們選擇的解決方案。

第二個解決方案是修補M2Crypto/BIO.py。具體而言,要修補實現BIO.readlines()的代碼以測試無或len(buf)== 0的m2.bio.gets()的返回值,並將兩者都視爲流結束。第三種解決方案是簡單地避免調用BIO.readlines(),並限制自己調用BIO.readline()(注 - 單線readline vs readlines),並測試BIO.readline()的返回值。無論是None還是len(buf)== 0.

第三種解決方案可能看起來不像是一種選擇 - 更像是迴避。但是如果您擔心將應用程序部署到M2Crypto可能無法修補的環境中,則此方法保證是最兼容的。

我們已將修補程序提交給記錄Heikki的開發者,但他還沒有機會審查我們的建議。在某種方式或某種方式的正式答案發展之前,我想分享我們的想法。

+0

順便說一句 - 我不知道開發商科瓦萊寧親自......但他的項目M2Crypto絕對是妙不可言。它不僅是Python/OpenSSL包裝器的特殊實現,而且是創建SWIG代碼的正確方法的一個例子 - 乾淨,簡單,通透等等......幹得好,先生。 – user590028 2012-02-15 15:18:32

0

此問題與Debian Linux中的bug #717675有關。

它在Fedora 21中無法重現,而且我沒有找到任何修改BIO.py_bio.i的Fedora修補程序。

這裏是一個被張貼Debian的補丁:

--- /usr/lib64/python2.7/site-packages/M2Crypto/BIO.py 2011-01-15 20:10:05.000000000 +0100 
+++ BIO.py 2015-05-20 09:24:46.600582999 +0200 
@@ -73,6 +73,8 @@ 
      buf=m2.bio_gets(self.bio, 4096) 
      if buf is None: 
       break 
+  if len(buf)==0: 
+  break 
      lines.append(buf) 
     return lines 
+0

的意見,或回答? – null 2015-05-20 13:52:16

+0

那麼我明白爲什麼在Fedora中這個bug是不可重現的。有一個補丁「m2crypto-0.21.1-timeouts.patch」,它簡單地在Connection.py中重寫函數「makefile」。在這個新函數中,調用了python socket.py中的經典_fileobject類。這有點奇怪,因爲它會避免BIO.py中定義的所有機制。意思是通過open_https返回的對象不再是BIO對象...因此m2crypto的好處的一部分會丟失,我認爲...... – Jessie 2015-05-22 15:23:40

+0

而且它是比評論更多的評論。 – Jessie 2015-05-22 16:11:59