Browse Source

[build] Round up SUBx deltas

The zbin compressor fixup utility rounds down file sizes before
calculating their difference.  This produces incorrect values and may
cause truncated gPXE images to be loaded at boot.

The following example explains the problem:
ilen    = 48 bytes     (uncompressed input file)
olen    = 17 bytes     (compressed output file)
divisor = 16 bytes     (paragraph granularity)
fixmeup = 3 paragraphs (value to fix up)

olen / divisor - ilen / divisor
= 1 - 3
= -2 paragraphs  (old delta calculation)

( align ( olen, divisor ) - align ( ilen, divisor ) ) / divisor
= 2 - 3
= -1 paragraphs  (new delta calculation)

If we perform the SUBx operation with old delta:
fixmeup + -2 = 1 paragraph gets loaded by the prefix

With the new delta:
fixmeup + -1 = 2 paragraphs get loaded by the prefix

The old delta calculation removes the last paragraph; the prefix will
load a truncated copy of gPXE into memory.  We need to load 2
paragraphs since olen is 17 bytes.  Loading only 1 paragraph (16
bytes) would truncate the last byte.

Signed-off-by: Michael Brown <mcb30@etherboot.org>
tags/v0.9.8
Stefan Hajnoczi 15 years ago
parent
commit
b149a99302
1 changed files with 10 additions and 7 deletions
  1. 10
    7
      src/util/zbin.c

+ 10
- 7
src/util/zbin.c View File

57
 	unsigned int num_entries;
57
 	unsigned int num_entries;
58
 };
58
 };
59
 
59
 
60
+static unsigned long align ( unsigned long value, unsigned long align ) {
61
+	return ( ( value + align - 1 ) & ~( align - 1 ) );
62
+}
63
+
60
 static int read_file ( const char *filename, void **buf, size_t *len ) {
64
 static int read_file ( const char *filename, void **buf, size_t *len ) {
61
 	FILE *file;
65
 	FILE *file;
62
 	struct stat stat;
66
 	struct stat stat;
140
 	struct zinfo_copy *copy = &zinfo->copy;
144
 	struct zinfo_copy *copy = &zinfo->copy;
141
 	size_t offset = copy->offset;
145
 	size_t offset = copy->offset;
142
 	size_t len = copy->len;
146
 	size_t len = copy->len;
143
-	unsigned int align = copy->align;
144
 
147
 
145
 	if ( ( offset + len ) > input->len ) {
148
 	if ( ( offset + len ) > input->len ) {
146
 		fprintf ( stderr, "Input buffer overrun on copy\n" );
149
 		fprintf ( stderr, "Input buffer overrun on copy\n" );
147
 		return -1;
150
 		return -1;
148
 	}
151
 	}
149
 
152
 
150
-	output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
153
+	output->len = align ( output->len, copy->align );
151
 	if ( ( output->len + len ) > output->max_len ) {
154
 	if ( ( output->len + len ) > output->max_len ) {
152
 		fprintf ( stderr, "Output buffer overrun on copy\n" );
155
 		fprintf ( stderr, "Output buffer overrun on copy\n" );
153
 		return -1;
156
 		return -1;
170
 	struct zinfo_pack *pack = &zinfo->pack;
173
 	struct zinfo_pack *pack = &zinfo->pack;
171
 	size_t offset = pack->offset;
174
 	size_t offset = pack->offset;
172
 	size_t len = pack->len;
175
 	size_t len = pack->len;
173
-	unsigned int align = pack->align;
174
 	unsigned long packed_len;
176
 	unsigned long packed_len;
175
 
177
 
176
 	if ( ( offset + len ) > input->len ) {
178
 	if ( ( offset + len ) > input->len ) {
178
 		return -1;
180
 		return -1;
179
 	}
181
 	}
180
 
182
 
181
-	output->len = ( ( output->len + align - 1 ) & ~( align - 1 ) );
183
+	output->len = align ( output->len, pack->align );
182
 	if ( output->len > output->max_len ) {
184
 	if ( output->len > output->max_len ) {
183
 		fprintf ( stderr, "Output buffer overrun on pack\n" );
185
 		fprintf ( stderr, "Output buffer overrun on pack\n" );
184
 		return -1;
186
 		return -1;
222
 	}
224
 	}
223
 
225
 
224
 	target = ( output->buf + offset );
226
 	target = ( output->buf + offset );
225
-	delta = ( ( output->len / subtract->divisor ) -
226
-		  ( input->len / subtract->divisor ) );
227
+	delta = ( ( align ( output->len, subtract->divisor ) -
228
+		    align ( input->len, subtract->divisor ) )
229
+		  / subtract->divisor );
227
 
230
 
228
 	switch ( datasize ) {
231
 	switch ( datasize ) {
229
 	case 1: {
232
 	case 1: {
251
 	}
254
 	}
252
 
255
 
253
 	if ( DEBUG ) {
256
 	if ( DEBUG ) {
254
-		fprintf ( stderr, "SUBx [%#zx,%#zx) (%#lx+(%#lx/%#lx)-(%#lx/%#lx)) = %#lx\n",
257
+		fprintf ( stderr, "SUBx [%#zx,%#zx) (%#lx+(%#lx/%#x)-(%#lx/%#x)) = %#lx\n",
255
 			  offset, ( offset + datasize ), old, output->len, subtract->divisor,
258
 			  offset, ( offset + datasize ), old, output->len, subtract->divisor,
256
 			  input->len, subtract->divisor, new );
259
 			  input->len, subtract->divisor, new );
257
 	}
260
 	}

Loading…
Cancel
Save