在OS X中从main返回时出现中止陷阱6,但在linux中没有
Abort trap 6 when returning from main in OS X but NOT on linux
我有一个程序,目前似乎在Linux (Ubuntu 14.04)上运行良好,但在OS X(10.11.6)上运行时,我得到一个中止陷阱6。我已经附上了我的代码,但我怀疑这个问题实际上并不与特定的代码有关。这段代码是为了一个课程项目,我并不是想要破解密码或其他东西。
下面是代码,我相信所有重要的东西都发生在main中。#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/conf.h>
#include <openssl/err.h>
#define KEY_BYTES KEY_LENGTH/8
#define KEY_LENGTH 128
unsigned char* h(unsigned char* p, unsigned char* hp);
void handleErrors(void);
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext);
//assumes we've already padded with zeros
unsigned char* h(unsigned char* p, unsigned char *hp){
encrypt((unsigned char*)"0000000000000000", KEY_BYTES, p , (unsigned char*)"0000000000000000", hp);
return hp;
}
void handleErrors(void)
{
printf("panic!!n");
//ERR_print_errors_fp(stderr); //sg: throw a real error you fool!
abort();
}
//sg: stolen from the evp man page
int encrypt(unsigned char *plaintext, int plaintext_len, unsigned char *key,
unsigned char *iv, unsigned char *ciphertext)
{
EVP_CIPHER_CTX *ctx;
int len;
int ciphertext_len;
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
/* Initialise the encryption operation. IMPORTANT - ensure you use a key
* and IV size appropriate for your cipher
* In this example we are using 256 bit AES (i.e. a 256 bit key). The
* IV size for *most* modes is the same as the block size. For AES this
* is 128 bits */
if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
handleErrors();
/* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len))
handleErrors();
ciphertext_len = len;
/* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors();
ciphertext_len += len;
/* Clean up */
EVP_CIPHER_CTX_free(ctx);
return ciphertext_len;
}
int main(){
/* Initialise the library */
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
OPENSSL_config(NULL);
EVP_CIPHER_CTX *ctx;
unsigned char hp[KEY_BYTES];
/* Create and initialise the context */
if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors();
h((unsigned char*) "1111111111111111", hp);
for(int i = 0; i < KEY_BYTES; i++){
printf("h(%i) = %xn", i, hp[i]);
}
return 0;
}
当在linux上运行时,我得到以下(这是我所期望的)
h(0) = 10
h(1) = df
h(2) = c1
h(3) = b5
h(4) = f6
h(5) = 6c
h(6) = fd
h(7) = 6a
h(8) = 1d
h(9) = c4
h(10) = 6d
h(11) = 66
h(12) = 90
h(13) = 7b
h(14) = ee
h(15) = b1
然而,当我在OS X上运行时,我得到以下内容:
h(0) = 10
h(1) = df
h(2) = c1
h(3) = b5
h(4) = f6
h(5) = 6c
h(6) = fd
h(7) = 6a
h(8) = 1d
h(9) = c4
h(10) = 6d
h(11) = 66
h(12) = 90
h(13) = 7b
h(14) = ee
h(15) = b1
Abort trap: 6
当我将它弹出到gdb中时,我得到以下
(gdb) r
Starting program: /Users/sgillen/Code/457/proj3/a.out
h(0) = 10
h(1) = df
h(2) = c1
h(3) = b5
h(4) = f6
h(5) = 6c
h(6) = fd
h(7) = 6a
h(8) = 1d
h(9) = c4
h(10) = 6d
h(11) = 66
h(12) = 90
h(13) = 7b
h(14) = ee
h(15) = b1
Program received signal SIGABRT, Aborted.
0x00007fff93150f06 in __pthread_kill () from /usr/lib/system/libsystem_kernel.dylib
(gdb) where
#0 0x00007fff93150f06 in __pthread_kill () from /usr/lib/system/libsystem_kernel.dylib
#1 0x00007fff97b374ec in pthread_kill () from /usr/lib/system/libsystem_pthread.dylib
#2 0x00007fff9ba8077f in __abort () from /usr/lib/system/libsystem_c.dylib
#3 0x00007fff9ba8105e in __stack_chk_fail () from /usr/lib/system/libsystem_c.dylib
#4 0x0000000100000ea9 in main () at gen_table.cpp:90
不确定如何在堆栈溢出时做行号,但gen_table.cpp的第90行是main中最后返回0的行号。
如果相关的话,我用下面的代码编译我的代码。
clang -Wall -std=c++11 gen_table.cpp -I/usr/local/opt/openssl/include/ -lcrypto -lssl -g
任何帮助都将非常感激,谢谢!
我找到了我的问题的答案,我想我会为任何遇到同样问题的人发布答案。问题是我重写了自己的堆栈。我使用的加密函数实际上是向hp写入32字节(这是堆栈上的16字节无符号字符)。所以我会销毁我自己的堆栈,但不会写入任何不属于我的进程的内存。这导致没有segfault,但当程序试图返回时,最终出现了问题。杀死我的确切原因取决于我如何编译我的代码。
我真的很惊讶valgrind没有发现这个。我仍然不知道为什么当用clang编译时,它似乎在linux上工作得很好(用g++编译时,我得到了一个堆栈粉碎检测到的错误)。
编辑:明确地说,解决方案是修复我的encrypt实现,使其只写入16字节。我只是通过注释EVP_EncryptFinal_ex调用来做到这一点。
相关文章:
- 代码在main()中运行,但在函数中出现错误
- 链接阶段在Ubuntu上失败,但在MacOS上失败
- 对C宏的未定义引用,但在定义它时会出现重新定义错误
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 断言中的Fold表达式在某些计算机上编译,但在其他计算机上不编译
- 换位表导致测试失败(但在游戏中运行良好)
- 库标题在标题中不可见,但在 cmake build 下.cpp文件中完全可见.为什么?
- 树莓上的 Libtorch 无法加载 pt 文件,但在 ubuntu 上工作
- 在成员dynamic_bitset上使用 boost::from_block_range 时出错,但在本地dynamic
- 编译在我的 Mac 上工作,但在集群 (Linux) 上不起作用
- 我编写了代码将十进制分数转换为其二进制等效数.它编译得很好,但在执行时挂起
- 我的代码运行良好,但在游戏循环中中断
- C++ assigment std::list:<typename>:itrator 在 main 中工作,但在方法中它不起作用
- C++代码在台式机上工作正常,但在笔记本电脑上则不行
- 实现 DFS 在较短的输入下工作正常,但在较大的输入下会抛出分段错误
- 点云库在VS 2019中不起作用,但在VS 2017中确实有效
- C++ Python 模块在 Blender 中崩溃,但在 Python 控制台中不会崩溃
- 分段 Linux Ubuntu 中的 g++ 错误,但在 Windows 中的 g++/MingW 中,在 C++ 中打
- 为什么数组大小信息可用于"sizeof"运算符和 delete[] 运算符,但在将数组作为参数传递到
- 在OS X中从main返回时出现中止陷阱6,但在linux中没有