gpt4 book ai didi

c - Pset4 (cs50) 恢复无法正常工作。它可以编译,但不能恢复超过 2 个 jpeg。检查 JPEG 签名是否有问题?

转载 作者:行者123 更新时间:2023-11-30 19:08:48 25 4
gpt4 key购买 nike

我正在学习如何编码,但我对此完全没有经验。我已经成功到达 PSET4 并陷入恢复状态。我已经在网上阅读了有关此问题的所有内容,我发现很多人都有与我类似的代码并且它有效。对我来说没有任何作用。请看一下并给我提示我做错了什么以及如何纠正。这是有关 pset4 recover 的所有内容我从这里下载了他们的card.raw card.raw

/** recovering JPEG files from a memory card
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef uint8_t BYTE;

int main(int argc, char* argv[])
{
// ensure proper usage
if (argc != 2)
{
fprintf(stderr,
"Usage: ./recover infile (the name of a forensic image from which to recover JPEGs)\n");
return 1;
}

// open input file (forensic image)
FILE* inptr = fopen(argv[1], "r");
if (inptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 2;
}

FILE* outptr = NULL;

// create a pointer array of 512 elements to store 512 bytes from the memory card
BYTE* buffer = malloc(sizeof(BYTE) * 512);
if (buffer == NULL)
{
return 3;
}

// count amount of jpeg files found
int jpeg = 0;

// string for a file name using sprintf
char filename[8] = { 0 };

// read memory card untill the end of file
while (fread(buffer, sizeof(BYTE) * 512, 1, inptr) != 0)
{
// check if jpeg is found
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff
&& (buffer[3] >= 0xe0 || buffer[3] <= 0xef))
{
if (jpeg > 0)
{
fclose(outptr);
}
sprintf(filename, "%03d.JPEG", jpeg);
outptr = fopen(filename, "w");
jpeg++;
}

if (jpeg > 0)
{
fwrite(buffer, sizeof(BYTE) * 512, 1, outptr);
}
}

// free memory
free(buffer);

// close filename
fclose(outptr);

// close input file (forensic image)
fclose(inptr);

return 0;
}

最佳答案

主要问题是您调用未定义的行为,因为filename不够大。 sprintf() 需要为您的代码设置 9 和 17 个字节,但您只有 8 个字节。因此存在缓冲区溢出。

只需更改:

char filename[8] = { 0 };

char filename[17] = { 0 };

因为您使用 int,所以该值是实现定义的,但在 ma​​ny 系统中具有 32 位的 int。因此,可能的值介于 -2^312^31 - 1 之间,最多为 11 个 char (-2147483648)。我们在“.JPEG”中添加了 char 的数量,即 5。我们有 16 个,但您忘记了 c 字符串的空终止字节。所以我们最多 17 个。

现代编译器警告您:gcc 版本 7.1.1 20170516 (GCC):

In function ‘main’:
warning: ‘sprintf’ writing a terminating nul past the end of the destination [-Wformat-overflow ]
sprintf(filename, "%03d.JPEG", jpeg++);
^
note: ‘sprintf’ output between 9 and 17 bytes into a destination of size 8
sprintf(filename, "%03d.JPEG", jpeg++);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

另外,您的 typedef 是无用的,因为 char 世界在 C 中始终是一个字节。更重要的是,您不需要一个字节,而是一个八位字节,例如 charuint8_t 在 C 中始终是一个八位字节。因此您不需要 typedef

再说一遍,您分配了缓冲区,但它没有用,因为您的缓冲区具有恒定的大小。所以创建一个数组就更简单了。

#include <stdint.h>
#include <stdio.h>

int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: ./recover infile (the name of a forensic image "
"from which to recover JPEGs)\n");
return 1;
}

FILE *inptr = fopen(argv[1], "r");
if (inptr == NULL) {
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 2;
}

FILE *outptr = NULL;
uint8_t buffer[512];
size_t const buffer_size = sizeof buffer / sizeof *buffer;
size_t jpeg = 0;
while (fread(buffer, sizeof *buffer, buffer_size, inptr) == buffer_size) {
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff &&
buffer[3] == 0xe0) {
if (outptr != NULL) {
fclose(outptr);
}

char filename[26];
sprintf(filename, "%03zu.JPEG", jpeg++);
outptr = fopen(filename, "w");
}
if (outptr != NULL) {
fwrite(buffer, sizeof *buffer, buffer_size, outptr);
}
}

if (outptr != NULL) {
fwrite(buffer, sizeof *buffer, buffer_size, outptr);
}

if (outptr != NULL) {
fclose(outptr);
}

fclose(inptr);
}

注意:这个例子显然并不完美,这会更好地为 jpeg 文件制作一个真正的解析器,以具有更好的控制流程。我们假设一切都会好起来的。

关于c - Pset4 (cs50) 恢复无法正常工作。它可以编译,但不能恢复超过 2 个 jpeg。检查 JPEG 签名是否有问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44349102/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com