mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
Backed out changeset 14fbd3cca8aa (bug 1806394) for causing build bustages in mar_read.c CLOSED TREE
This commit is contained in:
parent
7abda4200c
commit
4da3fbb6cb
@ -55,8 +55,7 @@ typedef struct SeenIndex_ {
|
||||
* Mozilla ARchive (MAR) file data structure
|
||||
*/
|
||||
struct MarFile_ {
|
||||
unsigned char* buffer; /* file buffer containing the entire MAR */
|
||||
size_t data_len; /* byte count of the data in the buffer */
|
||||
FILE* fp; /* file pointer to the archive */
|
||||
MarItem* item_table[TABLESIZE]; /* hash table of files in the archive */
|
||||
SeenIndex* index_list; /* file indexes processed */
|
||||
int item_table_is_valid; /* header and index validation flag */
|
||||
@ -73,29 +72,16 @@ typedef struct MarFile_ MarFile;
|
||||
*/
|
||||
typedef int (*MarItemCallback)(MarFile* mar, const MarItem* item, void* data);
|
||||
|
||||
enum MarReadResult_ {
|
||||
MAR_READ_SUCCESS,
|
||||
MAR_IO_ERROR,
|
||||
MAR_MEM_ERROR,
|
||||
MAR_FILE_TOO_BIG_ERROR,
|
||||
};
|
||||
|
||||
typedef enum MarReadResult_ MarReadResult;
|
||||
|
||||
/**
|
||||
* Open a MAR file for reading.
|
||||
* @param path Specifies the path to the MAR file to open. This path must
|
||||
* be compatible with fopen.
|
||||
* @param out_mar Out-parameter through which the created MarFile structure is
|
||||
* returned. Guaranteed to be a valid structure if
|
||||
* MAR_READ_SUCCESS is returned. Otherwise NULL will be
|
||||
* assigned.
|
||||
* @return NULL if an error occurs.
|
||||
*/
|
||||
MarReadResult mar_open(const char* path, MarFile** out_mar);
|
||||
MarFile* mar_open(const char* path);
|
||||
|
||||
#ifdef XP_WIN
|
||||
MarReadResult mar_wopen(const wchar_t* path, MarFile** out_mar);
|
||||
MarFile* mar_wopen(const wchar_t* path);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -104,49 +90,6 @@ MarReadResult mar_wopen(const wchar_t* path, MarFile** out_mar);
|
||||
*/
|
||||
void mar_close(MarFile* mar);
|
||||
|
||||
/**
|
||||
* Reads the specified amount of data from the buffer in MarFile that contains
|
||||
* the entirety of the MAR file data.
|
||||
* @param mar The MAR file to read from.
|
||||
* @param dest The buffer to read into.
|
||||
* @param position The byte index to start reading from the MAR at.
|
||||
* On success, position will be incremented by size.
|
||||
* @param size The number of bytes to read.
|
||||
* @return 0 If the specified amount of data was read.
|
||||
* -1 If the buffer MAR is not large enough to read the
|
||||
* specified amount of data at the specified position.
|
||||
*/
|
||||
int mar_read_buffer(MarFile* mar, void* dest, size_t* position, size_t size);
|
||||
|
||||
/**
|
||||
* Reads the specified amount of data from the buffer in MarFile that contains
|
||||
* the entirety of the MAR file data. If there isn't that much data remaining,
|
||||
* reads as much as possible.
|
||||
* @param mar The MAR file to read from.
|
||||
* @param dest The buffer to read into.
|
||||
* @param position The byte index to start reading from the MAR at.
|
||||
* This function will increment position by the number of bytes
|
||||
* copied.
|
||||
* @param size The maximum number of bytes to read.
|
||||
* @return The number of bytes copied into dest.
|
||||
*/
|
||||
int mar_read_buffer_max(MarFile* mar, void* dest, size_t* position,
|
||||
size_t size);
|
||||
|
||||
/**
|
||||
* Increments position by distance. Checks that the resulting position is still
|
||||
* within the bounds of the buffer. Much like fseek, this will allow position to
|
||||
* be successfully placed just after the end of the buffer.
|
||||
* @param mar The MAR file to read from.
|
||||
* @param position The byte index to start reading from the MAR at.
|
||||
* On success, position will be incremented by size.
|
||||
* @param distance The number of bytes to move forward by.
|
||||
* @return 0 If position was successfully moved.
|
||||
* -1 If moving position by distance would move it outside the
|
||||
* bounds of the buffer.
|
||||
*/
|
||||
int mar_buffer_seek(MarFile* mar, size_t* position, size_t distance);
|
||||
|
||||
/**
|
||||
* Find an item in the MAR file by name.
|
||||
* @param mar The MarFile object to query.
|
||||
|
@ -75,8 +75,8 @@ int mar_extract(const char* path) {
|
||||
MarFile* mar;
|
||||
int rv;
|
||||
|
||||
MarReadResult result = mar_open(path, &mar);
|
||||
if (result != MAR_READ_SUCCESS) {
|
||||
mar = mar_open(path);
|
||||
if (!mar) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -112,28 +112,25 @@ static int mar_consume_index(MarFile* mar, char** buf, const char* buf_end) {
|
||||
static int mar_read_index(MarFile* mar) {
|
||||
char id[MAR_ID_SIZE], *buf, *bufptr, *bufend;
|
||||
uint32_t offset_to_index, size_of_index;
|
||||
size_t mar_position = 0;
|
||||
|
||||
/* verify MAR ID */
|
||||
if (mar_read_buffer(mar, id, &mar_position, MAR_ID_SIZE) != 0) {
|
||||
fseek(mar->fp, 0, SEEK_SET);
|
||||
if (fread(id, MAR_ID_SIZE, 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
if (memcmp(id, MAR_ID, MAR_ID_SIZE) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mar_read_buffer(mar, &offset_to_index, &mar_position, sizeof(uint32_t)) !=
|
||||
0) {
|
||||
if (fread(&offset_to_index, sizeof(uint32_t), 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
offset_to_index = ntohl(offset_to_index);
|
||||
|
||||
mar_position = 0;
|
||||
if (mar_buffer_seek(mar, &mar_position, offset_to_index) != 0) {
|
||||
if (fseek(mar->fp, offset_to_index, SEEK_SET)) {
|
||||
return -1;
|
||||
}
|
||||
if (mar_read_buffer(mar, &size_of_index, &mar_position, sizeof(uint32_t)) !=
|
||||
0) {
|
||||
if (fread(&size_of_index, sizeof(uint32_t), 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
size_of_index = ntohl(size_of_index);
|
||||
@ -142,7 +139,7 @@ static int mar_read_index(MarFile* mar) {
|
||||
if (!buf) {
|
||||
return -1;
|
||||
}
|
||||
if (mar_read_buffer(mar, buf, &mar_position, size_of_index) != 0) {
|
||||
if (fread(buf, size_of_index, 1, mar->fp) != 1) {
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
@ -213,94 +210,50 @@ static int mar_insert_offset(MarFile* mar, uint32_t offset, uint32_t length) {
|
||||
|
||||
/**
|
||||
* Internal shared code for mar_open and mar_wopen.
|
||||
* Reads the entire MAR into memory. Fails if it is bigger than
|
||||
* MAX_SIZE_OF_MAR_FILE bytes.
|
||||
* On failure, will fclose(fp).
|
||||
*/
|
||||
static MarReadResult mar_fpopen(FILE* fp, MarFile** out_mar) {
|
||||
*out_mar = NULL;
|
||||
static MarFile* mar_fpopen(FILE* fp) {
|
||||
MarFile* mar;
|
||||
|
||||
mar = (MarFile*)malloc(sizeof(*mar));
|
||||
if (!mar) {
|
||||
return MAR_MEM_ERROR;
|
||||
}
|
||||
|
||||
off_t buffer_size = -1;
|
||||
if (fseeko(fp, 0, SEEK_END) == 0) {
|
||||
buffer_size = ftello(fp);
|
||||
}
|
||||
rewind(fp);
|
||||
if (buffer_size < 0) {
|
||||
fprintf(stderr, "Warning: MAR size could not be determined\n");
|
||||
buffer_size = MAX_SIZE_OF_MAR_FILE;
|
||||
}
|
||||
if (buffer_size > MAX_SIZE_OF_MAR_FILE) {
|
||||
fprintf(stderr, "ERROR: MAR exceeds maximum size (%li)\n", buffer_size);
|
||||
free(mar);
|
||||
return MAR_FILE_TOO_BIG_ERROR;
|
||||
}
|
||||
|
||||
mar->buffer = malloc(buffer_size);
|
||||
if (!mar->buffer) {
|
||||
fprintf(stderr, "ERROR: MAR buffer could not be allocated\n");
|
||||
free(mar);
|
||||
return MAR_MEM_ERROR;
|
||||
}
|
||||
mar->data_len = fread(mar->buffer, 1, buffer_size, fp);
|
||||
if (fgetc(fp) != EOF) {
|
||||
fprintf(stderr, "ERROR: File is larger than buffer (%li)\n", buffer_size);
|
||||
free(mar->buffer);
|
||||
free(mar);
|
||||
return MAR_IO_ERROR;
|
||||
}
|
||||
if (ferror(fp)) {
|
||||
fprintf(stderr, "ERROR: Failed to read MAR\n");
|
||||
free(mar->buffer);
|
||||
free(mar);
|
||||
return MAR_IO_ERROR;
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mar->fp = fp;
|
||||
mar->item_table_is_valid = 0;
|
||||
memset(mar->item_table, 0, sizeof(mar->item_table));
|
||||
mar->index_list = NULL;
|
||||
|
||||
*out_mar = mar;
|
||||
return MAR_READ_SUCCESS;
|
||||
return mar;
|
||||
}
|
||||
|
||||
MarReadResult mar_open(const char* path, MarFile** out_mar) {
|
||||
*out_mar = NULL;
|
||||
|
||||
MarFile* mar_open(const char* path) {
|
||||
FILE* fp;
|
||||
|
||||
fp = fopen(path, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: could not open file in mar_open()\n");
|
||||
perror(path);
|
||||
return MAR_IO_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MarReadResult result = mar_fpopen(fp, out_mar);
|
||||
fclose(fp);
|
||||
return result;
|
||||
return mar_fpopen(fp);
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
MarReadResult mar_wopen(const wchar_t* path, MarFile** out_mar) {
|
||||
*out_mar = NULL;
|
||||
|
||||
MarFile* mar_wopen(const wchar_t* path) {
|
||||
FILE* fp;
|
||||
|
||||
_wfopen_s(&fp, path, L"rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: could not open file in mar_wopen()\n");
|
||||
_wperror(path);
|
||||
return MAR_IO_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MarReadResult result = mar_fpopen(fp, out_mar);
|
||||
fclose(fp);
|
||||
return result;
|
||||
return mar_fpopen(fp);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -309,7 +262,7 @@ void mar_close(MarFile* mar) {
|
||||
SeenIndex* index;
|
||||
int i;
|
||||
|
||||
free(mar->buffer);
|
||||
fclose(mar->fp);
|
||||
|
||||
for (i = 0; i < TABLESIZE; ++i) {
|
||||
item = mar->item_table[i];
|
||||
@ -329,61 +282,10 @@ void mar_close(MarFile* mar) {
|
||||
free(mar);
|
||||
}
|
||||
|
||||
int mar_read_buffer(MarFile* mar, void* dest, size_t* position, size_t size) {
|
||||
// size may be provided by the MAR, which we may not have finished validating
|
||||
// the signature on yet. Make sure not to trust it in a way that could
|
||||
// cause an overflow.
|
||||
if (size > mar->data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (*position > mar->data_len - size) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(dest, mar->buffer + *position, size);
|
||||
*position += size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mar_read_buffer_max(MarFile* mar, void* dest, size_t* position,
|
||||
size_t size) {
|
||||
// size may be provided by the MAR, which we may not have finished validating
|
||||
// the signature on yet. Make sure not to trust it in a way that could
|
||||
// cause an overflow.
|
||||
if (mar->data_len <= *position) {
|
||||
return 0;
|
||||
}
|
||||
size_t read_count = mar->data_len - *position;
|
||||
if (read_count > size) {
|
||||
read_count = size;
|
||||
}
|
||||
memcpy(dest, mar->buffer + *position, read_count);
|
||||
*position += read_count;
|
||||
return read_count;
|
||||
}
|
||||
|
||||
int mar_buffer_seek(MarFile* mar, size_t* position, size_t distance) {
|
||||
// distance may be provided by the MAR, which we may not have finished
|
||||
// validating the signature on yet. Make sure not to trust it in a way that
|
||||
// could cause an overflow.
|
||||
if (distance > mar->data_len) {
|
||||
return -1;
|
||||
}
|
||||
if (*position > mar->data_len - distance) {
|
||||
return -1;
|
||||
}
|
||||
*position += distance;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the MAR file information.
|
||||
*
|
||||
* @param mar An open MAR file.
|
||||
* @param mar_position The current position in the MAR.
|
||||
* Its value will be updated to the current
|
||||
* position in the MAR after the function exits.
|
||||
* Since its initial value will never actually be
|
||||
* used, this is effectively an outparam.
|
||||
* @param fp An opened MAR file in read mode.
|
||||
* @param hasSignatureBlock Optional out parameter specifying if the MAR
|
||||
* file has a signature block or not.
|
||||
* @param numSignatures Optional out parameter for storing the number
|
||||
@ -398,11 +300,10 @@ int mar_buffer_seek(MarFile* mar, size_t* position, size_t distance) {
|
||||
* hasAdditionalBlocks is not equal to 0.
|
||||
* @return 0 on success and non-zero on failure.
|
||||
*/
|
||||
int get_open_mar_file_info(MarFile* mar, size_t* mar_position,
|
||||
int* hasSignatureBlock, uint32_t* numSignatures,
|
||||
int* hasAdditionalBlocks,
|
||||
uint32_t* offsetAdditionalBlocks,
|
||||
uint32_t* numAdditionalBlocks) {
|
||||
int get_mar_file_info_fp(FILE* fp, int* hasSignatureBlock,
|
||||
uint32_t* numSignatures, int* hasAdditionalBlocks,
|
||||
uint32_t* offsetAdditionalBlocks,
|
||||
uint32_t* numAdditionalBlocks) {
|
||||
uint32_t offsetToIndex, offsetToContent, signatureCount, signatureLen, i;
|
||||
|
||||
/* One of hasSignatureBlock or hasAdditionalBlocks must be non NULL */
|
||||
@ -411,27 +312,24 @@ int get_open_mar_file_info(MarFile* mar, size_t* mar_position,
|
||||
}
|
||||
|
||||
/* Skip to the start of the offset index */
|
||||
*mar_position = 0;
|
||||
if (mar_buffer_seek(mar, mar_position, MAR_ID_SIZE) != 0) {
|
||||
if (fseek(fp, MAR_ID_SIZE, SEEK_SET)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the offset to the index. */
|
||||
if (mar_read_buffer(mar, &offsetToIndex, mar_position,
|
||||
sizeof(offsetToIndex)) != 0) {
|
||||
if (fread(&offsetToIndex, sizeof(offsetToIndex), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
offsetToIndex = ntohl(offsetToIndex);
|
||||
|
||||
if (numSignatures) {
|
||||
/* Skip past the MAR file size field */
|
||||
if (mar_buffer_seek(mar, mar_position, sizeof(uint64_t)) != 0) {
|
||||
if (fseek(fp, sizeof(uint64_t), SEEK_CUR)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the number of signatures field */
|
||||
if (mar_read_buffer(mar, numSignatures, mar_position,
|
||||
sizeof(*numSignatures)) != 0) {
|
||||
if (fread(numSignatures, sizeof(*numSignatures), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
*numSignatures = ntohl(*numSignatures);
|
||||
@ -439,19 +337,17 @@ int get_open_mar_file_info(MarFile* mar, size_t* mar_position,
|
||||
|
||||
/* Skip to the first index entry past the index size field
|
||||
We do it in 2 calls because offsetToIndex + sizeof(uint32_t)
|
||||
could overflow in theory. */
|
||||
*mar_position = 0;
|
||||
if (mar_buffer_seek(mar, mar_position, offsetToIndex) != 0) {
|
||||
could oerflow in theory. */
|
||||
if (fseek(fp, offsetToIndex, SEEK_SET)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mar_buffer_seek(mar, mar_position, sizeof(uint32_t)) != 0) {
|
||||
if (fseek(fp, sizeof(uint32_t), SEEK_CUR)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the first offset to content field. */
|
||||
if (mar_read_buffer(mar, &offsetToContent, mar_position,
|
||||
sizeof(offsetToContent)) != 0) {
|
||||
if (fread(&offsetToContent, sizeof(offsetToContent), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
offsetToContent = ntohl(offsetToContent);
|
||||
@ -472,14 +368,12 @@ int get_open_mar_file_info(MarFile* mar, size_t* mar_position,
|
||||
}
|
||||
|
||||
/* Skip to the start of the signature block */
|
||||
*mar_position = 0;
|
||||
if (mar_buffer_seek(mar, mar_position, SIGNATURE_BLOCK_OFFSET) != 0) {
|
||||
if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get the number of signatures */
|
||||
if (mar_read_buffer(mar, &signatureCount, mar_position,
|
||||
sizeof(signatureCount)) != 0) {
|
||||
if (fread(&signatureCount, sizeof(signatureCount), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
signatureCount = ntohl(signatureCount);
|
||||
@ -493,50 +387,38 @@ int get_open_mar_file_info(MarFile* mar, size_t* mar_position,
|
||||
/* Skip past the whole signature block */
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
/* Skip past the signature algorithm ID */
|
||||
if (mar_buffer_seek(mar, mar_position, sizeof(uint32_t)) != 0) {
|
||||
if (fseek(fp, sizeof(uint32_t), SEEK_CUR)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the signature length and skip past the signature */
|
||||
if (mar_read_buffer(mar, &signatureLen, mar_position, sizeof(uint32_t)) !=
|
||||
0) {
|
||||
if (fread(&signatureLen, sizeof(uint32_t), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
signatureLen = ntohl(signatureLen);
|
||||
if (mar_buffer_seek(mar, mar_position, signatureLen) != 0) {
|
||||
if (fseek(fp, signatureLen, SEEK_CUR)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (*mar_position <= (size_t)INT64_MAX &&
|
||||
(int64_t)mar_position == (int64_t)offsetToContent) {
|
||||
if ((int64_t)ftell(fp) == (int64_t)offsetToContent) {
|
||||
*hasAdditionalBlocks = 0;
|
||||
} else {
|
||||
if (numAdditionalBlocks) {
|
||||
/* We have an additional block, so read in the number of additional blocks
|
||||
and set the offset. */
|
||||
*hasAdditionalBlocks = 1;
|
||||
if (mar_read_buffer(mar, numAdditionalBlocks, mar_position,
|
||||
sizeof(uint32_t)) != 0) {
|
||||
if (fread(numAdditionalBlocks, sizeof(uint32_t), 1, fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
*numAdditionalBlocks = ntohl(*numAdditionalBlocks);
|
||||
if (offsetAdditionalBlocks) {
|
||||
if (*mar_position > (size_t)UINT32_MAX) {
|
||||
return -1;
|
||||
}
|
||||
*offsetAdditionalBlocks = (uint32_t)*mar_position;
|
||||
*offsetAdditionalBlocks = ftell(fp);
|
||||
}
|
||||
} else if (offsetAdditionalBlocks) {
|
||||
/* numAdditionalBlocks is not specified but offsetAdditionalBlocks
|
||||
is, so fill it! */
|
||||
if (mar_buffer_seek(mar, mar_position, sizeof(uint32_t)) != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (*mar_position > (size_t)UINT32_MAX) {
|
||||
return -1;
|
||||
}
|
||||
*offsetAdditionalBlocks = (uint32_t)*mar_position;
|
||||
*offsetAdditionalBlocks = ftell(fp) + sizeof(uint32_t);
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,15 +436,16 @@ int get_open_mar_file_info(MarFile* mar, size_t* mar_position,
|
||||
int read_product_info_block(char* path,
|
||||
struct ProductInformationBlock* infoBlock) {
|
||||
int rv;
|
||||
MarFile* mar;
|
||||
MarReadResult result = mar_open(path, &mar);
|
||||
if (result != MAR_READ_SUCCESS) {
|
||||
MarFile mar;
|
||||
mar.fp = fopen(path, "rb");
|
||||
if (!mar.fp) {
|
||||
fprintf(stderr,
|
||||
"ERROR: could not open file in read_product_info_block()\n");
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
rv = mar_read_product_info_block(mar, infoBlock);
|
||||
mar_close(mar);
|
||||
rv = mar_read_product_info_block(&mar, infoBlock);
|
||||
fclose(mar.fp);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -579,14 +462,13 @@ int mar_read_product_info_block(MarFile* mar,
|
||||
uint32_t offsetAdditionalBlocks, numAdditionalBlocks, additionalBlockSize,
|
||||
additionalBlockID;
|
||||
int hasAdditionalBlocks;
|
||||
size_t mar_position = 0;
|
||||
|
||||
/* The buffer size is 97 bytes because the MAR channel name < 64 bytes, and
|
||||
product version < 32 bytes + 3 NULL terminator bytes. */
|
||||
char buf[MAXADDITIONALBLOCKSIZE + 1] = {'\0'};
|
||||
if (get_open_mar_file_info(mar, &mar_position, NULL, NULL,
|
||||
&hasAdditionalBlocks, &offsetAdditionalBlocks,
|
||||
&numAdditionalBlocks) != 0) {
|
||||
if (get_mar_file_info_fp(mar->fp, NULL, NULL, &hasAdditionalBlocks,
|
||||
&offsetAdditionalBlocks,
|
||||
&numAdditionalBlocks) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -594,8 +476,8 @@ int mar_read_product_info_block(MarFile* mar,
|
||||
in a MAR file so check if any exist and process the first found */
|
||||
if (numAdditionalBlocks > 0) {
|
||||
/* Read the additional block size */
|
||||
if (mar_read_buffer(mar, &additionalBlockSize, &mar_position,
|
||||
sizeof(additionalBlockSize)) != 0) {
|
||||
if (fread(&additionalBlockSize, sizeof(additionalBlockSize), 1, mar->fp) !=
|
||||
1) {
|
||||
return -1;
|
||||
}
|
||||
additionalBlockSize = ntohl(additionalBlockSize) -
|
||||
@ -608,8 +490,7 @@ int mar_read_product_info_block(MarFile* mar,
|
||||
}
|
||||
|
||||
/* Read the additional block ID */
|
||||
if (mar_read_buffer(mar, &additionalBlockID, &mar_position,
|
||||
sizeof(additionalBlockID)) != 0) {
|
||||
if (fread(&additionalBlockID, sizeof(additionalBlockID), 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
additionalBlockID = ntohl(additionalBlockID);
|
||||
@ -618,7 +499,7 @@ int mar_read_product_info_block(MarFile* mar,
|
||||
const char* location;
|
||||
int len;
|
||||
|
||||
if (mar_read_buffer(mar, buf, &mar_position, additionalBlockSize) != 0) {
|
||||
if (fread(buf, additionalBlockSize, 1, mar->fp) != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -647,7 +528,7 @@ int mar_read_product_info_block(MarFile* mar,
|
||||
return 0;
|
||||
} else {
|
||||
/* This is not the additional block you're looking for. Move along. */
|
||||
if (mar_buffer_seek(mar, &mar_position, additionalBlockSize) != 0) {
|
||||
if (fseek(mar->fp, additionalBlockSize, SEEK_CUR)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -720,7 +601,6 @@ int mar_enum_items(MarFile* mar, MarItemCallback callback, void* closure) {
|
||||
int mar_read(MarFile* mar, const MarItem* item, int offset, uint8_t* buf,
|
||||
int bufsize) {
|
||||
int nr;
|
||||
size_t mar_position = 0;
|
||||
|
||||
if (offset == (int)item->length) {
|
||||
return 0;
|
||||
@ -734,15 +614,11 @@ int mar_read(MarFile* mar, const MarItem* item, int offset, uint8_t* buf,
|
||||
nr = bufsize;
|
||||
}
|
||||
|
||||
// Avoid adding item->offset and offset directly, just in case of overflow.
|
||||
if (mar_buffer_seek(mar, &mar_position, item->offset)) {
|
||||
return -1;
|
||||
}
|
||||
if (mar_buffer_seek(mar, &mar_position, offset)) {
|
||||
if (fseek(mar->fp, item->offset + offset, SEEK_SET)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mar_read_buffer_max(mar, buf, &mar_position, nr);
|
||||
return fread(buf, 1, nr, mar->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -768,18 +644,17 @@ int get_mar_file_info(const char* path, int* hasSignatureBlock,
|
||||
uint32_t* offsetAdditionalBlocks,
|
||||
uint32_t* numAdditionalBlocks) {
|
||||
int rv;
|
||||
MarFile* mar;
|
||||
size_t mar_position = 0;
|
||||
MarReadResult result = mar_open(path, &mar);
|
||||
if (result != MAR_READ_SUCCESS) {
|
||||
fprintf(stderr, "ERROR: could not read file in get_mar_file_info()\n");
|
||||
FILE* fp = fopen(path, "rb");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: could not open file in get_mar_file_info()\n");
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rv = get_open_mar_file_info(mar, &mar_position, hasSignatureBlock,
|
||||
numSignatures, hasAdditionalBlocks,
|
||||
offsetAdditionalBlocks, numAdditionalBlocks);
|
||||
rv = get_mar_file_info_fp(fp, hasSignatureBlock, numSignatures,
|
||||
hasAdditionalBlocks, offsetAdditionalBlocks,
|
||||
numAdditionalBlocks);
|
||||
|
||||
mar_close(mar);
|
||||
fclose(fp);
|
||||
return rv;
|
||||
}
|
||||
|
@ -111,8 +111,8 @@ static int mar_test_callback(MarFile* mar, const MarItem* item, void* unused) {
|
||||
static int mar_test(const char* path) {
|
||||
MarFile* mar;
|
||||
|
||||
MarReadResult result = mar_open(path, &mar);
|
||||
if (result != MAR_READ_SUCCESS) {
|
||||
mar = mar_open(path);
|
||||
if (!mar) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -393,9 +393,8 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
|
||||
if (!rv) {
|
||||
MarFile* mar;
|
||||
MarReadResult result = mar_open(argv[2], &mar);
|
||||
if (result == MAR_READ_SUCCESS) {
|
||||
MarFile* mar = mar_open(argv[2]);
|
||||
if (mar) {
|
||||
rv = mar_verify_signatures(mar, certBuffers, fileSizes, certCount);
|
||||
mar_close(mar);
|
||||
} else {
|
||||
|
@ -56,38 +56,35 @@ int mar_read_entire_file(const char* filePath, uint32_t maxSize,
|
||||
return result;
|
||||
}
|
||||
|
||||
int mar_extract_and_verify_signatures(MarFile* mar,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey* keys,
|
||||
uint32_t keyCount);
|
||||
int mar_verify_extracted_signatures(MarFile* mar,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey* keys,
|
||||
const uint8_t* const* extractedSignatures,
|
||||
uint32_t keyCount, uint32_t* numVerified);
|
||||
int mar_extract_and_verify_signatures_fp(FILE* fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey* keys,
|
||||
uint32_t keyCount);
|
||||
int mar_verify_signatures_for_fp(FILE* fp, CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey* keys,
|
||||
const uint8_t* const* extractedSignatures,
|
||||
uint32_t keyCount, uint32_t* numVerified);
|
||||
|
||||
/**
|
||||
* Reads the specified number of bytes from the MAR buffer and
|
||||
* Reads the specified number of bytes from the file pointer and
|
||||
* stores them in the passed buffer.
|
||||
*
|
||||
* @param mar An opened MAR
|
||||
* @param mar_position
|
||||
* Our current position within the MAR file buffer.
|
||||
* @param fp The file pointer to read from.
|
||||
* @param buffer The buffer to store the read results.
|
||||
* @param size The number of bytes to read, buffer must be
|
||||
* at least of this size.
|
||||
* @param ctxs Pointer to the first element in an array of verify context.
|
||||
* @param count The number of elements in ctxs
|
||||
* @param err The name of what is being written to in case of error.
|
||||
* @return CryptoX_Success on success
|
||||
* CryptoX_Error on error
|
||||
* @return 0 on success
|
||||
* -1 on read error
|
||||
* -2 on verify update error
|
||||
*/
|
||||
CryptoX_Result ReadAndUpdateVerifyContext(MarFile* mar, size_t* mar_position,
|
||||
void* buffer, uint32_t size,
|
||||
CryptoX_SignatureHandle* ctxs,
|
||||
uint32_t count, const char* err) {
|
||||
int ReadAndUpdateVerifyContext(FILE* fp, void* buffer, uint32_t size,
|
||||
CryptoX_SignatureHandle* ctxs, uint32_t count,
|
||||
const char* err) {
|
||||
uint32_t k;
|
||||
if (!mar || !mar_position || !buffer || !ctxs || count == 0 || !err) {
|
||||
if (!fp || !buffer || !ctxs || count == 0 || !err) {
|
||||
fprintf(stderr, "ERROR: Invalid parameter specified.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
@ -96,7 +93,7 @@ CryptoX_Result ReadAndUpdateVerifyContext(MarFile* mar, size_t* mar_position,
|
||||
return CryptoX_Success;
|
||||
}
|
||||
|
||||
if (mar_read_buffer(mar, buffer, mar_position, size) != 0) {
|
||||
if (fread(buffer, size, 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read %s\n", err);
|
||||
return CryptoX_Error;
|
||||
}
|
||||
@ -104,7 +101,7 @@ CryptoX_Result ReadAndUpdateVerifyContext(MarFile* mar, size_t* mar_position,
|
||||
for (k = 0; k < count; k++) {
|
||||
if (CryptoX_Failed(CryptoX_VerifyUpdate(&ctxs[k], buffer, size))) {
|
||||
fprintf(stderr, "ERROR: Could not update verify context for %s\n", err);
|
||||
return CryptoX_Error;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
return CryptoX_Success;
|
||||
@ -139,6 +136,11 @@ int mar_verify_signatures(MarFile* mar, const uint8_t* const* certData,
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (!mar->fp) {
|
||||
fprintf(stderr, "ERROR: MAR file is not open.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (CryptoX_Failed(CryptoX_InitCryptoProvider(&provider))) {
|
||||
fprintf(stderr, "ERROR: Could not init crytpo library.\n");
|
||||
goto failure;
|
||||
@ -152,7 +154,7 @@ int mar_verify_signatures(MarFile* mar, const uint8_t* const* certData,
|
||||
}
|
||||
}
|
||||
|
||||
rv = mar_extract_and_verify_signatures(mar, provider, keys, certCount);
|
||||
rv = mar_extract_and_verify_signatures_fp(mar->fp, provider, keys, certCount);
|
||||
|
||||
failure:
|
||||
|
||||
@ -167,41 +169,50 @@ failure:
|
||||
|
||||
/**
|
||||
* Extracts each signature from the specified MAR file,
|
||||
* then calls mar_verify_extracted_signatures to verify each signature.
|
||||
* then calls mar_verify_signatures_for_fp to verify each signature.
|
||||
*
|
||||
* @param mar An opened MAR
|
||||
* @param fp An opened MAR file handle
|
||||
* @param provider A library provider
|
||||
* @param keys The public keys to use to verify the MAR
|
||||
* @param keyCount The number of keys pointed to by keys
|
||||
* @return 0 on success
|
||||
*/
|
||||
int mar_extract_and_verify_signatures(MarFile* mar,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey* keys,
|
||||
uint32_t keyCount) {
|
||||
int mar_extract_and_verify_signatures_fp(FILE* fp,
|
||||
CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey* keys,
|
||||
uint32_t keyCount) {
|
||||
uint32_t signatureCount, signatureLen, numVerified = 0;
|
||||
uint32_t signatureAlgorithmIDs[MAX_SIGNATURES];
|
||||
uint8_t* extractedSignatures[MAX_SIGNATURES];
|
||||
uint32_t i;
|
||||
size_t mar_position = 0;
|
||||
|
||||
memset(signatureAlgorithmIDs, 0, sizeof(signatureAlgorithmIDs));
|
||||
memset(extractedSignatures, 0, sizeof(extractedSignatures));
|
||||
|
||||
if (!mar) {
|
||||
if (!fp) {
|
||||
fprintf(stderr, "ERROR: Invalid file pointer passed.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* To protect against invalid MAR files, we assumes that the MAR file
|
||||
size is less than or equal to MAX_SIZE_OF_MAR_FILE. */
|
||||
if (fseeko(fp, 0, SEEK_END)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to the end of the MAR file.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
if (ftello(fp) > MAX_SIZE_OF_MAR_FILE) {
|
||||
fprintf(stderr, "ERROR: MAR file is too large to be verified.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* Skip to the start of the signature block */
|
||||
if (mar_buffer_seek(mar, &mar_position, SIGNATURE_BLOCK_OFFSET) != 0) {
|
||||
if (fseeko(fp, SIGNATURE_BLOCK_OFFSET, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to the signature block.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
|
||||
/* Get the number of signatures */
|
||||
if (mar_read_buffer(mar, &signatureCount, &mar_position,
|
||||
sizeof(signatureCount)) != 0) {
|
||||
if (fread(&signatureCount, sizeof(signatureCount), 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read number of signatures.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
@ -217,21 +228,19 @@ int mar_extract_and_verify_signatures(MarFile* mar,
|
||||
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
/* Get the signature algorithm ID */
|
||||
if (mar_read_buffer(mar, &signatureAlgorithmIDs[i], &mar_position,
|
||||
sizeof(uint32_t)) != 0) {
|
||||
if (fread(&signatureAlgorithmIDs[i], sizeof(uint32_t), 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read signatures algorithm ID.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
signatureAlgorithmIDs[i] = ntohl(signatureAlgorithmIDs[i]);
|
||||
|
||||
if (mar_read_buffer(mar, &signatureLen, &mar_position, sizeof(uint32_t)) !=
|
||||
0) {
|
||||
if (fread(&signatureLen, sizeof(uint32_t), 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read signatures length.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
signatureLen = ntohl(signatureLen);
|
||||
|
||||
/* To protect against invalid input make sure the signature length
|
||||
/* To protected against invalid input make sure the signature length
|
||||
isn't too big. */
|
||||
if (signatureLen > MAX_SIGNATURE_LENGTH) {
|
||||
fprintf(stderr, "ERROR: Signature length is too large to verify.\n");
|
||||
@ -240,11 +249,10 @@ int mar_extract_and_verify_signatures(MarFile* mar,
|
||||
|
||||
extractedSignatures[i] = malloc(signatureLen);
|
||||
if (!extractedSignatures[i]) {
|
||||
fprintf(stderr, "ERROR: Could not allocate buffer for signature.\n");
|
||||
fprintf(stderr, "ERROR: Could allocate buffer for signature.\n");
|
||||
return CryptoX_Error;
|
||||
}
|
||||
if (mar_read_buffer(mar, extractedSignatures[i], &mar_position,
|
||||
signatureLen) != 0) {
|
||||
if (fread(extractedSignatures[i], signatureLen, 1, fp) != 1) {
|
||||
fprintf(stderr, "ERROR: Could not read extracted signature.\n");
|
||||
for (i = 0; i < signatureCount; ++i) {
|
||||
free(extractedSignatures[i]);
|
||||
@ -262,8 +270,11 @@ int mar_extract_and_verify_signatures(MarFile* mar,
|
||||
}
|
||||
}
|
||||
|
||||
if (mar_verify_extracted_signatures(
|
||||
mar, provider, keys, (const uint8_t* const*)extractedSignatures,
|
||||
if (ftello(fp) == -1) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
if (mar_verify_signatures_for_fp(
|
||||
fp, provider, keys, (const uint8_t* const*)extractedSignatures,
|
||||
signatureCount, &numVerified) == CryptoX_Error) {
|
||||
return CryptoX_Error;
|
||||
}
|
||||
@ -293,7 +304,7 @@ int mar_extract_and_verify_signatures(MarFile* mar,
|
||||
* certificate given, etc. The signature count must exactly match the number of
|
||||
* certificates given, and all signature verifications must succeed.
|
||||
*
|
||||
* @param mar An opened MAR
|
||||
* @param fp An opened MAR file handle
|
||||
* @param provider A library provider
|
||||
* @param keys A pointer to the first element in an
|
||||
* array of keys.
|
||||
@ -304,18 +315,18 @@ int mar_extract_and_verify_signatures(MarFile* mar,
|
||||
* the number of verified signatures.
|
||||
* This information can be useful for printing
|
||||
* error messages.
|
||||
* @return CryptoX_Success on success, *numVerified == signatureCount.
|
||||
* @return 0 on success, *numVerified == signatureCount.
|
||||
*/
|
||||
CryptoX_Result mar_verify_extracted_signatures(
|
||||
MarFile* mar, CryptoX_ProviderHandle provider, CryptoX_PublicKey* keys,
|
||||
const uint8_t* const* extractedSignatures, uint32_t signatureCount,
|
||||
uint32_t* numVerified) {
|
||||
int mar_verify_signatures_for_fp(FILE* fp, CryptoX_ProviderHandle provider,
|
||||
CryptoX_PublicKey* keys,
|
||||
const uint8_t* const* extractedSignatures,
|
||||
uint32_t signatureCount,
|
||||
uint32_t* numVerified) {
|
||||
CryptoX_SignatureHandle signatureHandles[MAX_SIGNATURES];
|
||||
char buf[BLOCKSIZE];
|
||||
uint32_t signatureLengths[MAX_SIGNATURES];
|
||||
uint32_t i;
|
||||
int rv = CryptoX_Error;
|
||||
size_t mar_position = 0;
|
||||
|
||||
memset(signatureHandles, 0, sizeof(signatureHandles));
|
||||
memset(signatureLengths, 0, sizeof(signatureLengths));
|
||||
@ -344,13 +355,19 @@ CryptoX_Result mar_verify_extracted_signatures(
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip to the start of the file */
|
||||
if (fseeko(fp, 0, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR: Could not seek to start of the file\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/* Bytes 0-3: MAR1
|
||||
Bytes 4-7: index offset
|
||||
Bytes 8-15: size of entire MAR
|
||||
*/
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(
|
||||
mar, &mar_position, buf, SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t),
|
||||
signatureHandles, signatureCount, "signature block"))) {
|
||||
fp, buf, SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t), signatureHandles,
|
||||
signatureCount, "signature block"))) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
@ -358,14 +375,14 @@ CryptoX_Result mar_verify_extracted_signatures(
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
/* Get the signature algorithm ID */
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(
|
||||
mar, &mar_position, &buf, sizeof(uint32_t), signatureHandles,
|
||||
signatureCount, "signature algorithm ID"))) {
|
||||
fp, &buf, sizeof(uint32_t), signatureHandles, signatureCount,
|
||||
"signature algorithm ID"))) {
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (CryptoX_Failed(ReadAndUpdateVerifyContext(
|
||||
mar, &mar_position, &signatureLengths[i], sizeof(uint32_t),
|
||||
signatureHandles, signatureCount, "signature length"))) {
|
||||
fp, &signatureLengths[i], sizeof(uint32_t), signatureHandles,
|
||||
signatureCount, "signature length"))) {
|
||||
goto failure;
|
||||
}
|
||||
signatureLengths[i] = ntohl(signatureLengths[i]);
|
||||
@ -375,15 +392,20 @@ CryptoX_Result mar_verify_extracted_signatures(
|
||||
}
|
||||
|
||||
/* Skip past the signature itself as those are not included */
|
||||
if (mar_buffer_seek(mar, &mar_position, signatureLengths[i]) != 0) {
|
||||
if (fseeko(fp, signatureLengths[i], SEEK_CUR)) {
|
||||
fprintf(stderr, "ERROR: Could not seek past signature.\n");
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the rest of the file after the signature block */
|
||||
while (mar_position < mar->data_len) {
|
||||
int numRead = mar_read_buffer_max(mar, buf, &mar_position, BLOCKSIZE);
|
||||
while (!feof(fp)) {
|
||||
int numRead = fread(buf, 1, BLOCKSIZE, fp);
|
||||
if (ferror(fp)) {
|
||||
fprintf(stderr, "ERROR: Error reading data block.\n");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
for (i = 0; i < signatureCount; i++) {
|
||||
if (CryptoX_Failed(
|
||||
CryptoX_VerifyUpdate(&signatureHandles[i], buf, numRead))) {
|
||||
|
@ -203,15 +203,12 @@ int ArchiveReader::Open(const NS_tchar* path) {
|
||||
}
|
||||
}
|
||||
|
||||
MarReadResult result =
|
||||
#ifdef XP_WIN
|
||||
mar_wopen(path, &mArchive);
|
||||
mArchive = mar_wopen(path);
|
||||
#else
|
||||
mar_open(path, &mArchive);
|
||||
mArchive = mar_open(path);
|
||||
#endif
|
||||
if (result == MAR_MEM_ERROR) {
|
||||
return ARCHIVE_READER_MEM_ERROR;
|
||||
} else if (result != MAR_READ_SUCCESS) {
|
||||
if (!mArchive) {
|
||||
return READ_ERROR;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user