malloc():损坏的顶部大小

问题描述 投票:0回答:2

我正在开发一个程序,可以解密文件中的某些文本行。首先,我创建的另一个源代码要求转换和一些文本。源代码对文本进行加密并将其写入文件中。

然后,我尝试使用下面的代码(另一个源代码)解密指定的文件。已获取文件名。从文件名中获取移位。文件中写入的每个字符都会被复制,并借助我也有的函数 caesar_decrypt -reversing caesar encrypt 移动移位值。但是,给定字符的 ascii 值必须在 32 到 127 之间才能转换为 ascii 值在 32 到 127 之间的另一个字符。

我定义了模函数,封装了余数运算符 - 正数的模 - 和负数的模。我还定义了 strip 函数,其工作方式与 python 中的 strip 函数相同。除了空格之外,它还会删除所有文字。我还有getIn(),就是python的input()。

我尝试通过打印和使用 gdb 进行调试。没有有效的结果。我在 stackoverflow 上研究过这个话题。找到一个条目。答案没有解决我的具体问题。

注意:我复制了整个程序,因为我认为您需要必要的详细信息。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <fcntl.h>

/*GETIN FUNCTION*/
char* getIn() 
{
    char *line = NULL, *tmp = NULL;
    size_t size = 0, index = 0;
    int ch = EOF;

    while (ch) 
    {
        ch = getc(stdin);

        /* Check if we need to stop. */
        if (ch == EOF || ch == '\n')
        ch = 0;

        /* Check if we need to expand. */
        if (size <= index) 
        {
            size += sizeof(char);
            tmp = realloc(line, size);
            if (!tmp) 
            {
                free(line);
                line = NULL;
                break;
            }
        line = tmp;
        }

    /* Actually store the thing. */
    line[index++] = ch;
    }

    return line;
}
/*FUNCTION THAT CONVERTS TO NUMERIC CHARACTER, PRECURSOR OF DIGITS OF SHIFT*/
char make_numeric(char ch)
{
    if(ch<91 && ch>63) return ch-16;
    if(ch<123 && ch>95) return ch-48;
    if(ch<58 && ch>47) return ch;
    return ch+16;
}

 /*STRIP FUNCTION*/
char* strip(char* str,int length)
{
    char *start=str,*end=&str[length-1];

    while(*start>0 && *start<33 || *start==127) ++start;
    if(!*start) return start;

    while(*end>=0 && *end<33 || *end==127) --end;
    ++end;
    *end=0;

    return start;
}
/*DECRYPTOR FUNCTION*/
char *caesar_decrypt(char *message_to_decrypt, void *shift)
{   
    int length=strlen(message_to_decrypt),i;
    char* decrypted_message;

    if(!message_to_decrypt) return NULL;

    if(!(decrypted_message=calloc(length+1,sizeof(char)))) return NULL;

    for(i=0;i<length;++i)
    {
    decrypted_message[i]=mod((message_to_decrypt[i]-33-*((int*)shift)),94)+33;
    }

return decrypted_message;
}   

/*THE MAIN PROGRAM*/
int main()
{

int shift,len_chshift,init,len_filename,i=0;
char *chshift,*line=NULL,*decrypted_line,*stripped_line,chinit,chlen_chshift;
char *filename=NULL,*newfilename=NULL;
FILE *oldfile=NULL;
FILE *newfile=NULL;
size_t lenline,len=0;

printf("-9");
/*FILENAME*/
printf("Enter the file name: ");
/*printf("-8");*/
filename=getIn();
/*printf("-7");*/
if(!access(filename,F_OK))
{
    len_filename=strlen(filename);
    /*printf("-6");*/
    i=len_filename;
    while(filename[i]!='.') --i;        
    chlen_chshift=filename[i-1];
    chlen_chshift=make_numeric(chlen_chshift);
    len_chshift=chlen_chshift-48;
    /*printf("-5");*/
    chshift=calloc(len_chshift+1,1);
    /*NEWFILENAME*/
    newfilename=calloc(i+1,1);
    /*printf("-4");*/
    strncpy(newfilename,filename,i);
    /*printf("-3");*/
    strcat(newfilename,"(decrypted).txt");
    /*printf("-2");*/
    chinit=make_numeric(filename[0]);
    init=chinit-48;
    /*SHIFT*/
    i=0;
    /*printf("-1");*/
    while(i!=len_chshift)
    {
        chshift[i]=make_numeric(filename[(i+1)*init]);
        ++i;
    }
    /*printf("0");*/
    shift=atoi(chshift);

    /*printf("1");*/
    if(!(oldfile=fopen(filename,"r")))
    {
        perror("Error");
        if(newfilename) free(newfilename);
        if(filename) free(filename);
        if(chshift) free(chshift);
        exit(1);
    }
    /*printf("2");*/

    if(!(newfile=fopen(newfilename,"+ab")))
    {
        perror("Error");
        if(newfilename) free(newfilename);
        if(filename) free(filename);
        if(chshift) free(chshift);
        fclose(oldfile);
        exit(1);
    }
    while ((lenline = getline(&line, &len, oldfile)) != -1)
    {
        stripped_line=strip(line,lenline);
        decrypted_line=caesar_decrypt(stripped_line, &shift);
        if(!decrypted_line)
        {
            printf("Could not allocate memory\n");
            if(newfilename) free(newfilename);
            if(filename) free(filename);
            if(chshift) free(chshift);
            exit(1);
        }

        fprintf(newfile,"%s\n",decrypted_line);

        if(decrypted_line) free(decrypted_line);
        decrypted_line=NULL;

        free(line);
        line=NULL;
        stripped_line=NULL;
        decrypted_line=NULL;
    }
    free(line);
    line=NULL;
}
else
{
    printf("Cannot access the file.");
    if(filename) free(filename);
    exit(0);
}

if(newfilename) free(newfilename);
if(filename) free(filename);
if(chshift) free(chshift);

fclose(oldfile);
fclose(newfile);
return 0;
}

程序需要创建一个文件,其上下文是另一个文件的解密克隆,其名称由用户在开头提供。然而,它在第一个 fopen 之前抛出:

malloc(): corrupted top size
Aborted (core dumped)

当我取消注释每个 printf 行时,它在 getIn() 和 printf("-7"); 行之间给出相同的错误。当 printfs 被注释时,我观察到 filename 保存了由 getIn() 返回的写入值。因此,我不认为 getIn() 是问题所在。

编辑(1):我添加了 2 个缺失的标头,但仍然引发相同的错误。

编辑(2):我删除了所有不必要的标题。

编辑(3):既然有人要求我,我将尝试通过一个例子来说明:假设我有一个名为

的文件
2/b*A".txt

用两行代码

%52
abcd

我将文件名输入到程序中。

1).之前的最后一个字符是,转换为数字2。我们知道shift是一个两位数。

2)第一个字符是起始符,即 2 ,是我们需要重复跳转的字符数。由于我们的班次编号为两位数,因此我们将跳转两个字符两次。

3)现在我们将字符 b 和 A 分别转换为 2 和 1。我们的移位是 21。第一个字符 %(37) 向后移动到 n(110) 等等,我们需要创建一个包含以下内容的新文件:

n~#
LMNO

我感谢任何帮助。先感谢您。另外,我提到的变量是特定区间之间的任意字符。详情请查看源代码,或者我建议你在本地工作,因为我提供了整个程序。

对于 ASCII 码: https://www.asciitable.com/

如果您对凯撒密码感兴趣: https://en.wikipedia.org/wiki/Caesar_cipher

c segmentation-fault malloc caesar-cipher
2个回答
14
投票

您的缓冲区溢出了

newfilename
:

/* here you declare that the string pointed to by newfilename may contain `i`
   chars + zero-termination...*/ 
newfilename=calloc(i+1,1);

/* Here `i` is less than `strlen(filename)`, so only i characters from `filename`
   will be copied, that does NOT include the zero-termination
   (but it will be zero-terminated because the last byte in the buffer was 
   already cleared by `calloc`) */ 
strncpy(newfilename,filename,i);


/* Here `newfilename` is full, and `strcat` will write outside buffer!! Whatever
   happens after this line is undefined behaviour */   
strcat(newfilename,"(decrypted).txt");

所以你必须分配足够的空间给

newfilename
:

newfilename = calloc (i + strlen("(decrypted).txt") + 1, 1);

0
投票

我遇到了类似的打印

malloc(): corrupted top size
Aborted

我花了一些时间才发现这个问题,尽管它是通过调用“new myClass();”引起的调用,没有明确的原因导致此问题,并且没有使用字符串或数组/缓冲区/内存复制来导致它。

TLDR:在 ICD 文件中使用

#pragma pack(push,1)
而没有使用以下
#pragma pack(pop)
会导致与本线程中提出的问题中描述的行为相同。

我将简要描述该结构(以解释为什么很难确定根本原因):

MyDeviceICD.h
- 描述设备接口的文件

IGeneralMgr.h
- 任何管理器都必须继承的管理器类的库接口,但由框架而不是应用程序开发人员管理。

IMyDeviceMgr.h/cpp
- 描述管理器接口并继承
IGeneralMgr.h

的类

CMyDeviceMgr.h/cpp
- 公开继承
IMyDeviceMgr
接口类并实现此类设备的通用功能的类。

CMySpecificVendorDeviceMgr.h/cpp
- 公开继承
CMyDeviceMgr
接口类并实现此类设备的特定功能的类。

当管理者工厂(另一个类)尝试使用配置文件提供的信息创建

CMySpecificVendorDeviceMgr
类的新对象时,出现崩溃。

在调查了链中的每个数据成员及其初始化方式之后,由于 GDB 回溯没有提供额外的有用输入,我不得不一步一步重新应用有问题的提交,直到找到根本原因。

我在这里分享这一点,因为这是我多次在线搜索此问题的地方,并且其他可能犯了与我的团队相同错误的人也将获得一些指导来检查

#pragma

© www.soinside.com 2019 - 2024. All rights reserved.