[syslinux] [PATCH 2/2] core/graphics: fix lss16 parsing

Charles (Chas) Williams 3chas3 at gmail.com
Fri Aug 21 06:10:29 PDT 2015


getnybble() needs to return four bits at a time from every byte.
During rle decode, rows are rounded to an integer number of bytes.
The rle length needs to be able to hold values > 255.

Signed-off-by: Chas Williams <3chas3 at gmail.com>
---
 core/graphics.c | 35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/core/graphics.c b/core/graphics.c
index 1604ab4..011be4a 100644
--- a/core/graphics.c
+++ b/core/graphics.c
@@ -54,6 +54,9 @@ typedef struct {
 
 static lssheader_t LSSHeader;
 
+static uint16_t buffer_empty = 1;
+static int buffer;
+
 #define LSSMagic	LSSHeader.LSSMagic
 #define GraphXSize	LSSHeader.GraphXSize
 #define GraphYSize	LSSHeader.GraphYSize
@@ -114,15 +117,17 @@ static int vgasetmode(void)
 
 static inline char getnybble(void)
 {
-	char data = getc(fd);
-
-	if (data & 0x10) {
-		data &= 0x0F;
-		return data;
+	if (buffer_empty) {
+		buffer_empty = 0;
+		buffer = getc(fd);
+		if (buffer == -1)
+			printf("EOF!\n");
+	} else {
+		buffer >>= 4;
+		buffer_empty = 1;
 	}
 
-	data = getc(fd);
-	return (data & 0x0F);
+	return buffer & 0xF;
 }
 
 /*
@@ -139,7 +144,9 @@ static void rledecode(uint8_t *out, size_t count)
 	size_t size = count;
 	uint8_t data;
 	int i;
+	uint16_t rle_len;
 
+	buffer_empty = 1;
 again:
 	for (i = 0; i < size; i++) {
 
@@ -156,20 +163,20 @@ again:
 		return;
 
 	/* Start of run sequence */
-	data = getnybble();
-	if (data == 0) {
+	rle_len = getnybble();
+	if (rle_len == 0) {
 		/* long run */
 		uint8_t hi;
 
-		data = getnybble();
+		rle_len = getnybble();
 		hi = getnybble();
 		hi <<= 4;
-		data |= hi;
-		data += 16;
+		rle_len |= hi;
+		rle_len += 16;
 	}
 
 	/* dorun */
-	for (i = 0; i < data; i++)
+	for (i = 0; i < rle_len; i++)
 		*out++ = prev_pixel;
 
 	size -= i;
@@ -249,7 +256,7 @@ __export void vgadisplayfile(FILE *_fd)
 
 	/* Load the header */
 	while (size--)
-		*p = getc(fd);
+		*p++ = getc(fd);
 
 	if (*p != EOF) {
 		com32sys_t ireg, oreg;
-- 
2.1.0





More information about the Syslinux mailing list