M2Crypto BIO.readlines зависает, python 2.7 - PullRequest
0 голосов
/ 14 февраля 2012

Мы находимся в процессе преобразования проекта на основе C ++ openssl в python с M2Crypto, и мы столкнулись с несколько необычной проблемой с подпрограммами BIO из M2Crypto. В частности, любой вызов BIO.readlines () навсегда зависает от файлового объекта.

Вот краткий пример того, что мы попробовали:

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 2 декабря 2010 FreeBSD 8.2-RELEASE-p4

Ответы [ 2 ]

0 голосов
/ 20 мая 2015

Эта проблема связана с ошибкой # 717675 в Debian Linux.

Это не воспроизводится в Fedora 21, и я не нашел никаких патчей для Fedora, которые бы модифицировали BIO.py или _bio.i.

Вот патч, который был опубликован для 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 голосов
/ 15 февраля 2012

В случае, если другие столкнутся с этим в будущем, я хотел бы поделиться нашим патчем.

--- 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, было три решения этой проблемы. Первый патч выложен выше. Поскольку мы считаем, что это соответствует назначению man-страницы для BIO_gets (), это решение мы выбрали.

Вторым решением было исправление M2Crypto / BIO.py. В частности, чтобы пропатчить код, который реализует BIO.readlines (), чтобы проверить возвращаемое значение из m2.bio.gets () для None или len (buf) == 0, и обрабатывать их как конец потока.

Третьим решением было просто избежать вызова BIO.readlines () и ограничиться вызовом BIO.readline () (примечание - одиночная readline против readlines) и проверить возвращаемое значение из BIO.readline () для None или len (buf) == 0.

Третье решение может показаться не слишком хорошим вариантом, а скорее избеганием. Но если вы беспокоитесь о развертывании приложения в среде, где M2Crypto не может быть исправлен, этот подход гарантированно будет наиболее совместимым.

Мы отправили наш патч разработчику записи Хейкки, но у него еще не было возможности рассмотреть наше предложение. Пока официальный ответ так или иначе не развился, я хотел поделиться нашими мыслями.

...