Я отвечаю на свой вопрос, когда обнаружил, в чем проблема. Это была даже не проблема OpenSSL.
Сначала просмотрите проблему GitHub: SSL_write () возвращает SSL_ERROR_SYSCALL, если размер равен 0
Мой код выглядит следующим образом:
SSL_write(ssl, foo(), var);
foo
создает полезную нагрузку и возвращает const char *
, а var
- длину этих данных. Дело в том, что они на самом деле являются функциями-членами и переменными-членами класса C ++, а var
устанавливается foo
. Согласно стандарту C ++ порядок вычисления аргументов функции не указан. Начиная с 5.2.2,
Порядок оценки аргументов не определен. Все побочные эффекты при оценке выражений аргументов вступают в силу до ввода функции.
Таким образом, третий параметр (var
) может быть оценен перед вторым параметром (foo()
) , Действительно, это то, что происходило в соответствии с результатами сборки программы. Ниже приведен пример.
class myclass {
public:
int l;
const char *foo(){
l = 10;
return "mystring";
}
};
int main()
{
SSL *ssl;
myclass instance;
SSL_write(ssl, instance.foo(), instance.l);
}
и сборка,
_ZN7myclass3fooEv:
.LFB1778:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movl $10, (%rax)
leaq .LC0(%rip), %rax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1778:
.size _ZN7myclass3fooEv, .-_ZN7myclass3fooEv
.text
.globl main
.type main, @function
main:
.LFB1779:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $40, %rsp
.cfi_offset 3, -24
movq %fs:40, %rax
movq %rax, -24(%rbp)
xorl %eax, %eax
movl -36(%rbp), %ebx
leaq -36(%rbp), %rax
movq %rax, %rdi
call _ZN7myclass3fooEv
movq %rax, %rcx
movq -32(%rbp), %rax
movl %ebx, %edx ; rdx is the third parameter, var. ebx was set before the foo() call
movq %rcx, %rsi ; rsi is the second parameter, return value of foo()
movq %rax, %rdi ; rdi is the first parameter, ssl
call SSL_write@PLT
movl $0, %eax
movq -24(%rbp), %rdx
После SSL_write
гарантированно будет выполнено foo()
и для var
установлено правильное значение Вот почему SSL_write
работал во второй раз, я полагаю. Более того, в документах на SSL_write
написано
Вы не должны вызывать SSL_write () с num = 0, это вернет ошибку. SSL_write_ex () может быть вызван с num = 0, но не будет отправлять данные приложения на одноранговый узел.