Reads and validates the bitmap header metadata from the context's file * object. Assumes the file pointer is at the start of the file. Returns 1 if * ok or 0 if error or invalid file. */
| 533 | * ok or 0 if error or invalid file. |
| 534 | */ |
| 535 | static int Validate(read_context * p_ctx) |
| 536 | { |
| 537 | if(!ReadHeader(&p_ctx->header, p_ctx->fp)) return 0; |
| 538 | if(!ReadInfo( &p_ctx->info, p_ctx->fp)) return 0; |
| 539 | |
| 540 | if(p_ctx->info.info_size > UINT32_MAX - BMP_HEADER_SIZE) return 0; |
| 541 | p_ctx->headers_size = BMP_HEADER_SIZE + p_ctx->info.info_size; |
| 542 | |
| 543 | if(p_ctx->header.data_offset < p_ctx->headers_size) return 0; |
| 544 | p_ctx->after_headers = p_ctx->header.data_offset - p_ctx->headers_size; |
| 545 | |
| 546 | if(p_ctx->info.width <= 0 || p_ctx->info.height == 0) return 0; |
| 547 | |
| 548 | if(!CanMakeSizeT(p_ctx->info.width)) return 0; |
| 549 | if(!CanNegate( p_ctx->info.height)) return 0; |
| 550 | p_ctx->lines = ((p_ctx->info.height < 0) ? |
| 551 | -p_ctx->info.height : |
| 552 | p_ctx->info.height); |
| 553 | |
| 554 | if(!(p_ctx->flags & BMPREAD_ANY_SIZE)) |
| 555 | { |
| 556 | /* Both of these values have just been checked against being negative, |
| 557 | * and thus it's safe to pass them on as uint32_t. |
| 558 | */ |
| 559 | if(!IsPowerOf2(p_ctx->info.width)) return 0; |
| 560 | if(!IsPowerOf2(p_ctx->lines)) return 0; |
| 561 | } |
| 562 | |
| 563 | switch(p_ctx->info.compression) |
| 564 | { |
| 565 | case COMPRESSION_NONE: |
| 566 | if(p_ctx->info.bits != 1 && p_ctx->info.bits != 4 && |
| 567 | p_ctx->info.bits != 8 && p_ctx->info.bits != 24) return 0; |
| 568 | break; |
| 569 | |
| 570 | case COMPRESSION_BITFIELDS: |
| 571 | if(p_ctx->info.bits != 16 && p_ctx->info.bits != 32) return 0; |
| 572 | break; |
| 573 | |
| 574 | default: /* No compression supported yet (TODO: handle RLE). */ |
| 575 | return 0; |
| 576 | } |
| 577 | |
| 578 | p_ctx->file_line_len = GetLineLength(p_ctx->info.width, p_ctx->info.bits); |
| 579 | if(p_ctx->file_line_len == 0) return 0; |
| 580 | |
| 581 | p_ctx->out_channels = ((p_ctx->flags & BMPREAD_ALPHA) ? 4 : 3); |
| 582 | |
| 583 | /* This check happens outside the following if, where it would seem to |
| 584 | * belong, because we make the same computation again in the future. |
| 585 | */ |
| 586 | if(!CanMultiply(p_ctx->info.width, p_ctx->out_channels)) return 0; |
| 587 | |
| 588 | if(p_ctx->flags & BMPREAD_BYTE_ALIGN) |
| 589 | p_ctx->out_line_len = (size_t)p_ctx->info.width * p_ctx->out_channels; |
| 590 | else |
| 591 | { |
| 592 | p_ctx->out_line_len = GetLineLength(p_ctx->info.width, |
no test coverage detected