Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(165)

Side by Side Diff: utility/bmpblk_utility.cc

Issue 6286157: Test BMP files more thoroughly to be sure they're valid. (Closed) Base URL: http://git.chromium.org/git/vboot_reference.git@master
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tests/bitmaps/NotReallyA.bmp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // Utility for manipulating firmware screen block (BMPBLOCK) in GBB. 5 // Utility for manipulating firmware screen block (BMPBLOCK) in GBB.
6 // 6 //
7 7
8 #include "bmpblk_utility.h" 8 #include "bmpblk_utility.h"
9 9
10 #include <assert.h> 10 #include <assert.h>
11 #include <errno.h> 11 #include <errno.h>
12 #include <getopt.h> 12 #include <getopt.h>
13 #include <stdarg.h> 13 #include <stdarg.h>
14 #include <stdio.h> 14 #include <stdio.h>
15 #include <stdlib.h> 15 #include <stdlib.h>
16 #include <string.h> 16 #include <string.h>
17 #include <yaml.h> 17 #include <yaml.h>
18 18
19 /* The offsets of width and height fields in a BMP file. 19 /* BMP header, used to validate image requirements
20 * See http://en.wikipedia.org/wiki/BMP_file_format */ 20 * See http://en.wikipedia.org/wiki/BMP_file_format
21 #define BMP_WIDTH_OFFSET 18 21 */
22 #define BMP_HEIGHT_OFFSET 22 22 typedef struct {
23 uint8_t CharB; // must be 'B'
24 uint8_t CharM; // must be 'M'
25 uint32_t Size;
26 uint16_t Reserved[2];
27 uint32_t ImageOffset;
28 uint32_t HeaderSize;
29 uint32_t PixelWidth;
30 uint32_t PixelHeight;
31 uint16_t Planes; // Must be 1 for x86
32 uint16_t BitPerPixel; // 1, 4, 8, or 24 for x86
33 uint32_t CompressionType; // must be 0 for x86
34 uint32_t ImageSize;
35 uint32_t XPixelsPerMeter;
36 uint32_t YPixelsPerMeter;
37 uint32_t NumberOfColors;
38 uint32_t ImportantColors;
39 } __attribute__((packed)) BMP_IMAGE_HEADER;
40
23 41
24 static void error(const char *format, ...) { 42 static void error(const char *format, ...) {
25 va_list ap; 43 va_list ap;
26 va_start(ap, format); 44 va_start(ap, format);
27 fprintf(stderr, "ERROR: "); 45 fprintf(stderr, "ERROR: ");
28 vfprintf(stderr, format, ap); 46 vfprintf(stderr, format, ap);
29 va_end(ap); 47 va_end(ap);
30 exit(1); 48 exit(1);
31 } 49 }
32 50
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 yaml_event_delete(&event); 143 yaml_event_delete(&event);
126 } 144 }
127 } 145 }
128 146
129 void BmpBlockUtil::parse_bmpblock(yaml_parser_t *parser) { 147 void BmpBlockUtil::parse_bmpblock(yaml_parser_t *parser) {
130 yaml_event_t event; 148 yaml_event_t event;
131 yaml_parser_parse(parser, &event); 149 yaml_parser_parse(parser, &event);
132 if (event.type != YAML_SCALAR_EVENT) { 150 if (event.type != YAML_SCALAR_EVENT) {
133 error("Syntax error in parsing bmpblock.\n"); 151 error("Syntax error in parsing bmpblock.\n");
134 } 152 }
135 config_.header.major_version = atoi((char*)event.data.scalar.value); 153 char wantversion[20];
136 config_.header.minor_version = atoi( 154 sprintf(wantversion, "%d.%d",
137 strchr((char*)event.data.scalar.value, '.') + 1); 155 BMPBLOCK_MAJOR_VERSION,
156 BMPBLOCK_MINOR_VERSION);
157 string gotversion = (char*)event.data.scalar.value;
158 if (gotversion != wantversion) {
159 error("Invalid version specified in config file\n");
160 }
138 yaml_event_delete(&event); 161 yaml_event_delete(&event);
139 } 162 }
140 163
141 void BmpBlockUtil::parse_images(yaml_parser_t *parser) { 164 void BmpBlockUtil::parse_images(yaml_parser_t *parser) {
142 yaml_event_t event; 165 yaml_event_t event;
143 string image_name, image_filename; 166 string image_name, image_filename;
144 expect_event(parser, YAML_MAPPING_START_EVENT); 167 expect_event(parser, YAML_MAPPING_START_EVENT);
145 for (;;) { 168 for (;;) {
146 yaml_parser_parse(parser, &event); 169 yaml_parser_parse(parser, &event);
147 switch (event.type) { 170 switch (event.type) {
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 } else { 321 } else {
299 content.assign(buffer.begin(), buffer.end()); 322 content.assign(buffer.begin(), buffer.end());
300 } 323 }
301 } 324 }
302 325
303 fclose(fp); 326 fclose(fp);
304 return content; 327 return content;
305 } 328 }
306 329
307 ImageFormat BmpBlockUtil::get_image_format(const string content) { 330 ImageFormat BmpBlockUtil::get_image_format(const string content) {
308 if (content[0] == 'B' && content[1] == 'M') 331 if (content.size() < sizeof(BMP_IMAGE_HEADER))
309 return FORMAT_BMP;
310 else
311 return FORMAT_INVALID; 332 return FORMAT_INVALID;
333 const BMP_IMAGE_HEADER *hdr = (const BMP_IMAGE_HEADER *)content.c_str();
334
335 if (hdr->CharB != 'B' || hdr->CharM != 'M' ||
336 hdr->Planes != 1 ||
337 hdr->CompressionType != 0 ||
338 (hdr->BitPerPixel != 1 && hdr->BitPerPixel != 4 &&
339 hdr->BitPerPixel != 8 && hdr->BitPerPixel != 24))
340 return FORMAT_INVALID;
341
342 return FORMAT_BMP;
312 } 343 }
313 344
314 uint32_t BmpBlockUtil::get_bmp_image_width(const string content) { 345 uint32_t BmpBlockUtil::get_bmp_image_width(const string content) {
315 const char *start = content.c_str(); 346 const BMP_IMAGE_HEADER *hdr = (const BMP_IMAGE_HEADER *)content.c_str();
316 uint32_t width = *(uint32_t*)(start + BMP_WIDTH_OFFSET); 347 return hdr->PixelWidth;
317 /* Do a rough verification. */
318 assert(width > 0 && width < 1600);
319 return width;
320 } 348 }
321 349
322 uint32_t BmpBlockUtil::get_bmp_image_height(const string content) { 350 uint32_t BmpBlockUtil::get_bmp_image_height(const string content) {
323 const char *start = content.c_str(); 351 const BMP_IMAGE_HEADER *hdr = (const BMP_IMAGE_HEADER *)content.c_str();
324 uint32_t height = *(uint32_t*)(start + BMP_HEIGHT_OFFSET); 352 return hdr->PixelHeight;
325 /* Do a rough verification. */
326 assert(height > 0 && height < 1000);
327 return height;
328 } 353 }
329 354
330 void BmpBlockUtil::fill_all_image_infos() { 355 void BmpBlockUtil::fill_all_image_infos() {
356 int errcnt = 0;
331 for (StrImageConfigMap::iterator it = config_.images_map.begin(); 357 for (StrImageConfigMap::iterator it = config_.images_map.begin();
332 it != config_.images_map.end(); 358 it != config_.images_map.end();
333 ++it) { 359 ++it) {
334 it->second.data.format = (uint32_t)get_image_format(it->second.raw_content); 360 it->second.data.format = (uint32_t)get_image_format(it->second.raw_content);
335 switch (it->second.data.format) { 361 switch (it->second.data.format) {
336 case FORMAT_BMP: 362 case FORMAT_BMP:
337 it->second.data.width = get_bmp_image_width(it->second.raw_content); 363 it->second.data.width = get_bmp_image_width(it->second.raw_content);
338 it->second.data.height = get_bmp_image_height(it->second.raw_content); 364 it->second.data.height = get_bmp_image_height(it->second.raw_content);
339 break; 365 break;
340 default: 366 default:
341 error("Unsupported image format.\n"); 367 fprintf(stderr, "Unsupported image format in %s\n",
368 it->second.filename.c_str());
369 errcnt++;
342 } 370 }
343 } 371 }
372 if (errcnt)
373 error("Unable to continue due to errors.\n");
344 } 374 }
345 375
346 void BmpBlockUtil::compress_all_images(const Compression compress) { 376 void BmpBlockUtil::compress_all_images(const Compression compress) {
347 switch (compress) { 377 switch (compress) {
348 case COMPRESS_NONE: 378 case COMPRESS_NONE:
349 for (StrImageConfigMap::iterator it = config_.images_map.begin(); 379 for (StrImageConfigMap::iterator it = config_.images_map.begin();
350 it != config_.images_map.end(); 380 it != config_.images_map.end();
351 ++it) { 381 ++it) {
352 it->second.data.compression = compress; 382 it->second.data.compression = compress;
353 it->second.compressed_content = it->second.raw_content; 383 it->second.compressed_content = it->second.raw_content;
354 it->second.data.compressed_size = it->second.compressed_content.size(); 384 it->second.data.compressed_size = it->second.compressed_content.size();
355 } 385 }
356 break; 386 break;
357 default: 387 default:
358 error("Unsupported data compression.\n"); 388 error("Unsupported data compression.\n");
359 } 389 }
360 } 390 }
361 391
362 void BmpBlockUtil::fill_bmpblock_header() { 392 void BmpBlockUtil::fill_bmpblock_header() {
363 memset(&config_.header, '\0', sizeof(config_.header)); 393 memset(&config_.header, '\0', sizeof(config_.header));
364 memcpy(&config_.header.signature, BMPBLOCK_SIGNATURE, 394 memcpy(&config_.header.signature, BMPBLOCK_SIGNATURE,
365 BMPBLOCK_SIGNATURE_SIZE); 395 BMPBLOCK_SIGNATURE_SIZE);
396 config_.header.major_version = BMPBLOCK_MAJOR_VERSION;
397 config_.header.minor_version = BMPBLOCK_MINOR_VERSION;
366 config_.header.number_of_localizations = config_.localizations.size(); 398 config_.header.number_of_localizations = config_.localizations.size();
367 config_.header.number_of_screenlayouts = config_.localizations[0].size(); 399 config_.header.number_of_screenlayouts = config_.localizations[0].size();
368 for (unsigned int i = 1; i < config_.localizations.size(); ++i) { 400 for (unsigned int i = 1; i < config_.localizations.size(); ++i) {
369 assert(config_.header.number_of_screenlayouts == 401 assert(config_.header.number_of_screenlayouts ==
370 config_.localizations[i].size()); 402 config_.localizations[i].size());
371 } 403 }
372 config_.header.number_of_imageinfos = config_.images_map.size(); 404 config_.header.number_of_imageinfos = config_.images_map.size();
373 } 405 }
374 406
375 void BmpBlockUtil::pack_bmpblock() { 407 void BmpBlockUtil::pack_bmpblock() {
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 574
543 if (options.extract_mode) { 575 if (options.extract_mode) {
544 /* TODO(waihong): Implement the extract mode. */ 576 /* TODO(waihong): Implement the extract mode. */
545 error("Extract mode hasn't been implemented yet.\n"); 577 error("Extract mode hasn't been implemented yet.\n");
546 } 578 }
547 579
548 return 0; 580 return 0;
549 } 581 }
550 582
551 #endif // WITH_UTIL_MAIN 583 #endif // WITH_UTIL_MAIN
OLDNEW
« no previous file with comments | « tests/bitmaps/NotReallyA.bmp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698