lib/jpeg: Replace decoder with Wuffs' implementation
To quote its repo[0]: Wuffs is a memory-safe programming language (and a standard library written in that language) for Wrangling Untrusted File Formats Safely. Wrangling includes parsing, decoding and encoding. It compiles its library, written in its own language, to a C/C++ source file that can then be used independently without needing support for the language. That library is now imported to src/vendorcode/wuffs/. This change modifies our linters to ignore that directory because it's supposed to contain the wuffs compiler's result verbatim. Nigel Tao provided an initial wrapper around wuffs' jpeg decoder that implements our JPEG API. I further changed it a bit regarding data placement, dropped stuff from our API that wasn't ever used, or isn't used anymore, and generally made it fit coreboot a bit better. Features are Nigel's, bugs are mine. This commit also adapts our jpeg fuzz test to work with the modified API. After limiting it to deal only with approximately screen sized inputs, it fuzzed for 25 hours CPU time without a single hang or crash. This is a notable improvement over running the test with our old decoder which crashes within a minute. Finally, I tried the new parser with a pretty-much-random JPEG file I got from the internet, and it just showed it (once the resolution matched), which is also a notable improvement over the old decoder which is very particular about the subset of JPEG it supports. In terms of code size, a QEmu build's ramstage increases from 128060 bytes decompressed (64121 bytes after LZMA) to 172304 bytes decompressed (82734 bytes after LZMA). [0] https://github.com/google/wuffs Change-Id: If8fa7da69da1ad412f27c2c5e882393c7739bc82 Signed-off-by: Patrick Georgi <patrick@coreboot.org> Based-on-work-by: Nigel Tao <nigeltao@golang.org> Reviewed-on: https://review.coreboot.org/c/coreboot/+/78271 Reviewed-by: Paul Menzel <paulepanter@mailbox.org> Reviewed-by: Martin L Roth <gaumless@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
committed by
Felix Held
parent
5466261019
commit
1d029b40c9
@ -14,34 +14,40 @@ void set_bootsplash(unsigned char *framebuffer, unsigned int x_resolution,
|
|||||||
unsigned int y_resolution, unsigned int bytes_per_line,
|
unsigned int y_resolution, unsigned int bytes_per_line,
|
||||||
unsigned int fb_resolution)
|
unsigned int fb_resolution)
|
||||||
{
|
{
|
||||||
|
if ((x_resolution > INT_MAX) || (y_resolution) > INT_MAX) {
|
||||||
|
printk(BIOS_ERR, "Display resolution way too large.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int xres = x_resolution, yres = y_resolution;
|
||||||
printk(BIOS_INFO, "Setting up bootsplash in %dx%d@%d\n", x_resolution, y_resolution,
|
printk(BIOS_INFO, "Setting up bootsplash in %dx%d@%d\n", x_resolution, y_resolution,
|
||||||
fb_resolution);
|
fb_resolution);
|
||||||
struct jpeg_decdata *decdata;
|
size_t filesize;
|
||||||
unsigned char *jpeg = cbfs_map("bootsplash.jpg", NULL);
|
unsigned char *jpeg = cbfs_map("bootsplash.jpg", &filesize);
|
||||||
if (!jpeg) {
|
if (!jpeg) {
|
||||||
printk(BIOS_ERR, "Could not find bootsplash.jpg\n");
|
printk(BIOS_ERR, "Could not find bootsplash.jpg\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int image_width, image_height;
|
unsigned int image_width, image_height;
|
||||||
jpeg_fetch_size(jpeg, &image_width, &image_height);
|
if (jpeg_fetch_size(jpeg, filesize, &image_width, &image_height) != 0) {
|
||||||
|
printk(BIOS_ERR, "Could not parse bootsplash.jpg\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
printk(BIOS_DEBUG, "Bootsplash image resolution: %dx%d\n", image_width, image_height);
|
printk(BIOS_DEBUG, "Bootsplash image resolution: %dx%d\n", image_width, image_height);
|
||||||
|
|
||||||
if (image_width > x_resolution || image_height > y_resolution) {
|
if (image_width > xres || image_height > yres) {
|
||||||
printk(BIOS_NOTICE, "Bootsplash image can't fit framebuffer.\n");
|
printk(BIOS_NOTICE, "Bootsplash image can't fit framebuffer.\n");
|
||||||
cbfs_unmap(jpeg);
|
cbfs_unmap(jpeg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* center image: */
|
/* center image: */
|
||||||
framebuffer += (y_resolution - image_height) / 2 * bytes_per_line +
|
framebuffer += (yres - image_height) / 2 * bytes_per_line
|
||||||
(x_resolution - image_width) / 2 * (fb_resolution / 8);
|
+ (xres - image_width) / 2 * (fb_resolution / 8);
|
||||||
|
|
||||||
decdata = malloc(sizeof(*decdata));
|
int ret = jpeg_decode(jpeg, filesize, framebuffer, image_width, image_height,
|
||||||
int ret = jpeg_decode(jpeg, framebuffer, image_width, image_height,
|
bytes_per_line, fb_resolution);
|
||||||
bytes_per_line, fb_resolution, decdata);
|
|
||||||
free(decdata);
|
|
||||||
cbfs_unmap(jpeg);
|
cbfs_unmap(jpeg);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
printk(BIOS_ERR, "Bootsplash could not be decoded. jpeg_decode returned %d.\n",
|
printk(BIOS_ERR, "Bootsplash could not be decoded. jpeg_decode returned %d.\n",
|
||||||
|
1059
src/lib/jpeg.c
1059
src/lib/jpeg.c
File diff suppressed because it is too large
Load Diff
@ -1,38 +1,16 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
|
|
||||||
/*
|
|
||||||
* a tiny jpeg decoder.
|
|
||||||
*
|
|
||||||
* written in August 2001 by Michael Schroeder <mls@suse.de>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __JPEG_H
|
#ifndef __JPEG_H
|
||||||
#define __JPEG_H
|
#define __JPEG_H
|
||||||
|
|
||||||
#define ERR_NO_SOI 1
|
#include <stdlib.h>
|
||||||
#define ERR_NOT_8BIT 2
|
|
||||||
#define ERR_HEIGHT_MISMATCH 3
|
|
||||||
#define ERR_WIDTH_MISMATCH 4
|
|
||||||
#define ERR_BAD_WIDTH_OR_HEIGHT 5
|
|
||||||
#define ERR_TOO_MANY_COMPPS 6
|
|
||||||
#define ERR_ILLEGAL_HV 7
|
|
||||||
#define ERR_QUANT_TABLE_SELECTOR 8
|
|
||||||
#define ERR_NOT_YCBCR_221111 9
|
|
||||||
#define ERR_UNKNOWN_CID_IN_SCAN 10
|
|
||||||
#define ERR_NOT_SEQUENTIAL_DCT 11
|
|
||||||
#define ERR_WRONG_MARKER 12
|
|
||||||
#define ERR_NO_EOI 13
|
|
||||||
#define ERR_BAD_TABLES 14
|
|
||||||
#define ERR_DEPTH_MISMATCH 15
|
|
||||||
|
|
||||||
struct jpeg_decdata {
|
#define JPEG_DECODE_FAILED 1
|
||||||
int dcts[6 * 64 + 16];
|
|
||||||
int out[64 * 6];
|
|
||||||
int dquant[3][64];
|
|
||||||
};
|
|
||||||
|
|
||||||
int jpeg_decode(unsigned char *, unsigned char *, int, int, int, int, struct jpeg_decdata *);
|
int jpeg_fetch_size(unsigned char *filedata, size_t filesize, unsigned int *width,
|
||||||
void jpeg_fetch_size(unsigned char *buf, int *width, int *height);
|
unsigned int *height);
|
||||||
int jpeg_check_size(unsigned char *, int, int);
|
int jpeg_decode(unsigned char *filedata, size_t filesize, unsigned char *framebuffer,
|
||||||
|
unsigned int width, unsigned int height, unsigned int bytes_per_line,
|
||||||
|
unsigned int depth);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
64187
src/vendorcode/wuffs/wuffs-v0.4.c
Normal file
64187
src/vendorcode/wuffs/wuffs-v0.4.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,18 +19,23 @@ int main(int argc, char **argv)
|
|||||||
if (fseek(f, 0, SEEK_SET) != 0)
|
if (fseek(f, 0, SEEK_SET) != 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
char *buf = malloc(len);
|
unsigned char *buf = malloc(len);
|
||||||
struct jpeg_decdata *decdata = malloc(sizeof(*decdata));
|
|
||||||
if (fread(buf, len, 1, f) != 1)
|
if (fread(buf, len, 1, f) != 1)
|
||||||
return 1;
|
return 1;
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
int width;
|
unsigned int width;
|
||||||
int height;
|
unsigned int height;
|
||||||
jpeg_fetch_size(buf, &width, &height);
|
if (jpeg_fetch_size(buf, len, &width, &height) != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((width > 6000) || (height > 6000)) {
|
||||||
|
// infeasible data set
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
//printf("width: %d, height: %d\n", width, height);
|
//printf("width: %d, height: %d\n", width, height);
|
||||||
char *pic = malloc(depth / 8 * width * height);
|
unsigned char *pic = malloc(depth / 8 * width * height);
|
||||||
int ret = jpeg_decode(buf, pic, width, height, width * depth / 8, depth, decdata);
|
int ret = jpeg_decode(buf, len, pic, width, height, width * depth / 8, depth);
|
||||||
//printf("ret: %x\n", ret);
|
//printf("ret: %x\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ INCLUDED_FILES='.*\.[ch]\|Kconfig.*$'
|
|||||||
|
|
||||||
EXCLUDED_DIRS="^payloads/libpayload/util/kconfig\|\
|
EXCLUDED_DIRS="^payloads/libpayload/util/kconfig\|\
|
||||||
^payloads/libpayload/curses/PDCurses\|\
|
^payloads/libpayload/curses/PDCurses\|\
|
||||||
|
^src/vendorcode/wuffs\|\
|
||||||
^util/coreboot-configurator\|\
|
^util/coreboot-configurator\|\
|
||||||
^util/crossgcc/patches\|\
|
^util/crossgcc/patches\|\
|
||||||
^util/inteltool\|\
|
^util/inteltool\|\
|
||||||
|
@ -14,5 +14,6 @@ LINTDIR="$(
|
|||||||
|
|
||||||
${FIND_FILES} | \
|
${FIND_FILES} | \
|
||||||
grep "^src/.*\.[csS]$" | \
|
grep "^src/.*\.[csS]$" | \
|
||||||
|
grep -v "^src/vendorcode/wuffs/" | \
|
||||||
xargs grep -Hn '^[[:space:]][[:space:]]*[a-z][a-z]*:[[:space:]]*$' | \
|
xargs grep -Hn '^[[:space:]][[:space:]]*[a-z][a-z]*:[[:space:]]*$' | \
|
||||||
grep -v "[^a-z_]default:"
|
grep -v "[^a-z_]default:"
|
||||||
|
Reference in New Issue
Block a user