mirror of
https://github.com/mtrojnar/osslsigncode.git
synced 2025-05-20 10:24:29 -05:00
Floyd's cycle-finding algorithm
This commit is contained in:
parent
6eaf0d9368
commit
b774a56aa9
49
msi.c
49
msi.c
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#define MIN(a,b) ((a) < (b) ? a : b)
|
#define MIN(a,b) ((a) < (b) ? a : b)
|
||||||
|
|
||||||
static int recurse_entry(MSI_FILE *msi, uint32_t entryID, MSI_DIRENT *parent, MSI_DIRENT *prev);
|
static int recurse_entry(MSI_FILE *msi, uint32_t entryID, MSI_DIRENT *parent);
|
||||||
|
|
||||||
/* Get absolute address from sector and offset */
|
/* Get absolute address from sector and offset */
|
||||||
static const u_char *sector_offset_to_address(MSI_FILE *msi, uint32_t sector, uint32_t offset)
|
static const u_char *sector_offset_to_address(MSI_FILE *msi, uint32_t sector, uint32_t offset)
|
||||||
@ -433,9 +433,11 @@ MSI_FILE *msi_file_new(char *buffer, uint32_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Recursively create a tree of MSI_DIRENT structures */
|
/* Recursively create a tree of MSI_DIRENT structures */
|
||||||
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT *prev, MSI_DIRENT **ret)
|
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret)
|
||||||
{
|
{
|
||||||
MSI_DIRENT *d, *dirent;
|
MSI_DIRENT *dirent;
|
||||||
|
static int cnt;
|
||||||
|
static MSI_DIRENT *tortoise, *hare;
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
return 1; /* OK */
|
return 1; /* OK */
|
||||||
@ -445,12 +447,12 @@ int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRE
|
|||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* detect loops in previously visited entries (parents, siblings) */
|
/* detect cycles in previously visited entries (parents, siblings) */
|
||||||
for (d = prev; d; d = d->prev) {
|
if (!ret) { /* initialized (non-root entry) */
|
||||||
if ((entry->leftSiblingID != NOSTREAM && d->entry->leftSiblingID == entry->leftSiblingID)
|
if ((entry->leftSiblingID != NOSTREAM && tortoise->entry->leftSiblingID == entry->leftSiblingID)
|
||||||
|| (entry->rightSiblingID != NOSTREAM && d->entry->rightSiblingID == entry->rightSiblingID)
|
|| (entry->rightSiblingID != NOSTREAM && tortoise->entry->rightSiblingID == entry->rightSiblingID)
|
||||||
|| (entry->childID != NOSTREAM && d->entry->childID == entry->childID)) {
|
|| (entry->childID != NOSTREAM && tortoise->entry->childID == entry->childID)) {
|
||||||
printf("Entry loop at ID: 0x%08X\n", entry->childID);
|
printf("MSI_ENTRY cycle detected at level %d\n", cnt);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -461,7 +463,19 @@ int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRE
|
|||||||
dirent->type = entry->type;
|
dirent->type = entry->type;
|
||||||
dirent->entry = entry;
|
dirent->entry = entry;
|
||||||
dirent->children = sk_MSI_DIRENT_new_null();
|
dirent->children = sk_MSI_DIRENT_new_null();
|
||||||
dirent->prev = prev;
|
dirent->next = NULL; /* fail-safe */
|
||||||
|
|
||||||
|
/* Floyd's cycle-finding algorithm */
|
||||||
|
if (!ret) { /* initialized (non-root entry) */
|
||||||
|
if (cnt++ & 1) /* move the tortoise every other invocation of msi_dirent_new() */
|
||||||
|
tortoise = tortoise->next;
|
||||||
|
hare->next = dirent; /* build a linked list of visited entries */
|
||||||
|
hare = dirent; /* move the hare every time */
|
||||||
|
} else { /* initialization needed (root entry) */
|
||||||
|
cnt = 0;
|
||||||
|
tortoise = dirent;
|
||||||
|
hare = dirent;
|
||||||
|
}
|
||||||
|
|
||||||
if (parent && !sk_MSI_DIRENT_push(parent->children, dirent)) {
|
if (parent && !sk_MSI_DIRENT_push(parent->children, dirent)) {
|
||||||
printf("Failed to insert MSI_DIRENT\n");
|
printf("Failed to insert MSI_DIRENT\n");
|
||||||
@ -470,9 +484,9 @@ int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRE
|
|||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!recurse_entry(msi, entry->leftSiblingID, parent, dirent)
|
if (!recurse_entry(msi, entry->leftSiblingID, parent)
|
||||||
|| !recurse_entry(msi, entry->rightSiblingID, parent, dirent)
|
|| !recurse_entry(msi, entry->rightSiblingID, parent)
|
||||||
|| (entry->type != DIR_STREAM && !recurse_entry(msi, entry->childID, dirent, dirent))) {
|
|| !recurse_entry(msi, entry->childID, dirent)) {
|
||||||
printf("Failed to add a sibling or a child to the tree\n");
|
printf("Failed to add a sibling or a child to the tree\n");
|
||||||
sk_MSI_DIRENT_free(dirent->children);
|
sk_MSI_DIRENT_free(dirent->children);
|
||||||
OPENSSL_free(dirent);
|
OPENSSL_free(dirent);
|
||||||
@ -486,11 +500,12 @@ int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRE
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add a sibling or a child to the tree */
|
/* Add a sibling or a child to the tree */
|
||||||
static int recurse_entry(MSI_FILE *msi, uint32_t entryID, MSI_DIRENT *parent, MSI_DIRENT *dirent) {
|
/* NOTE: These links are a tree, not a linked list */
|
||||||
/* NOTE : These links are a tree, not a linked list */
|
static int recurse_entry(MSI_FILE *msi, uint32_t entryID, MSI_DIRENT *parent)
|
||||||
|
{
|
||||||
MSI_ENTRY *node;
|
MSI_ENTRY *node;
|
||||||
|
|
||||||
/* The special value NOSTREAM (0xFFFFFFFF) is used as a terminator */
|
/* The special NOSTREAM (0xFFFFFFFF) value is used as a terminator */
|
||||||
if (entryID == NOSTREAM) /* stop condition */
|
if (entryID == NOSTREAM) /* stop condition */
|
||||||
return 1; /* OK */
|
return 1; /* OK */
|
||||||
|
|
||||||
@ -500,7 +515,7 @@ static int recurse_entry(MSI_FILE *msi, uint32_t entryID, MSI_DIRENT *parent, MS
|
|||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!msi_dirent_new(msi, node, parent, dirent, NULL)) {
|
if (!msi_dirent_new(msi, node, parent, NULL)) {
|
||||||
OPENSSL_free(node);
|
OPENSSL_free(node);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
|
4
msi.h
4
msi.h
@ -145,7 +145,7 @@ typedef struct msi_dirent_struct {
|
|||||||
uint8_t type;
|
uint8_t type;
|
||||||
MSI_ENTRY *entry;
|
MSI_ENTRY *entry;
|
||||||
STACK_OF(MSI_DIRENT) *children;
|
STACK_OF(MSI_DIRENT) *children;
|
||||||
struct msi_dirent_struct *prev; /* detect loops */
|
struct msi_dirent_struct *next; /* for cycle detection */
|
||||||
} MSI_DIRENT;
|
} MSI_DIRENT;
|
||||||
|
|
||||||
DEFINE_STACK_OF(MSI_DIRENT)
|
DEFINE_STACK_OF(MSI_DIRENT)
|
||||||
@ -204,7 +204,7 @@ int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, uint32_t offset, char *buffer
|
|||||||
MSI_FILE *msi_file_new(char *buffer, uint32_t len);
|
MSI_FILE *msi_file_new(char *buffer, uint32_t len);
|
||||||
void msi_file_free(MSI_FILE *msi);
|
void msi_file_free(MSI_FILE *msi);
|
||||||
MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi);
|
MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi);
|
||||||
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT *prev, MSI_DIRENT **ret);
|
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret);
|
||||||
MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse);
|
MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse);
|
||||||
void msi_dirent_free(MSI_DIRENT *dirent);
|
void msi_dirent_free(MSI_DIRENT *dirent);
|
||||||
int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root);
|
int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root);
|
||||||
|
@ -2919,7 +2919,7 @@ static int msi_verify_header(char *indata, uint32_t filesize, MSI_PARAMS *msipar
|
|||||||
printf("Failed to get file entry\n");
|
printf("Failed to get file entry\n");
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
}
|
}
|
||||||
if (!msi_dirent_new(msiparams->msi, root, NULL, NULL, &root_dir)) {
|
if (!msi_dirent_new(msiparams->msi, root, NULL, &root_dir)) {
|
||||||
printf("Failed to parse MSI_DIRENT struct\n");
|
printf("Failed to parse MSI_DIRENT struct\n");
|
||||||
OPENSSL_free(root);
|
OPENSSL_free(root);
|
||||||
return 0; /* FAILED */
|
return 0; /* FAILED */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user