Module: wine Branch: master Commit: 9b65338ef9980a562197e3513ab009b0b133ae4d URL: http://source.winehq.org/git/wine.git/?a=commit;h=9b65338ef9980a562197e3513a...
Author: Juan Lang juan.lang@gmail.com Date: Wed May 13 12:36:42 2009 -0700
inetmib1: Make sure the successor to an item doesn't have an identical key as it, to prevent infinite loops in table enumeration.
---
dlls/inetmib1/main.c | 78 +++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/dlls/inetmib1/main.c b/dlls/inetmib1/main.c index 91f5fd5..a6995ff 100644 --- a/dlls/inetmib1/main.c +++ b/dlls/inetmib1/main.c @@ -323,7 +323,27 @@ static DWORD oidToIpAddr(AsnObjectIdentifier *oid) typedef void (*oidToKeyFunc)(AsnObjectIdentifier *oid, void *dst); typedef int (*compareFunc)(const void *key, const void *value);
-static UINT findValueInTable(AsnObjectIdentifier *oid, +/* Finds the first value in the table that matches key. Returns its 1-based + * index if found, or 0 if not found. + */ +static UINT findValueInTable(const void *key, + struct GenericTable *table, size_t tableEntrySize, compareFunc compare) +{ + UINT index = 0; + void *value; + + value = bsearch(key, table->entries, table->numEntries, tableEntrySize, + compare); + if (value) + index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize + 1; + return index; +} + +/* Finds the first value in the table that matches oid, using makeKey to + * convert the oid to a key for comparison. Returns the value's 1-based + * index if found, or 0 if not found. + */ +static UINT findOidInTable(AsnObjectIdentifier *oid, struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, compareFunc compare) { @@ -332,14 +352,50 @@ static UINT findValueInTable(AsnObjectIdentifier *oid,
if (key) { - void *value; + makeKey(oid, key); + index = findValueInTable(key, table, tableEntrySize, compare); + HeapFree(GetProcessHeap(), 0, key); + } + return index; +} + +/* Finds the first successor to the value in the table that does matches oid, + * using makeKey to convert the oid to a key for comparison. A successor is + * a value that does not match oid, so if multiple entries match an oid, only + * the first will ever be returned using this method. + * Returns the successor's 1-based index if found, or 0 if not found. + */ +static UINT findNextOidInTable(AsnObjectIdentifier *oid, + struct GenericTable *table, size_t tableEntrySize, oidToKeyFunc makeKey, + compareFunc compare) +{ + UINT index = 0; + void *key = HeapAlloc(GetProcessHeap(), 0, tableEntrySize);
+ if (key) + { makeKey(oid, key); - value = bsearch(key, table->entries, table->numEntries, tableEntrySize, - compare); - if (value) - index = ((BYTE *)value - (BYTE *)table->entries) / tableEntrySize - + 1; + index = findValueInTable(key, table, tableEntrySize, compare); + if (index == 0) + { + /* Not found in table. If it's less than the first entry, return + * the first index. Otherwise just return 0 and let the caller + * handle finding the successor. + */ + if (compare(key, table->entries) < 0) + index = 1; + } + else + { + /* Skip any entries that match the same key. This enumeration will + * be incomplete, but it's what Windows appears to do if there are + * multiple entries with the same index in a table, and it avoids + * an infinite loop. + */ + for (++index; index <= table->numEntries && compare(key, + &table->entries[tableEntrySize * index]) == 0; ++index) + ; + } HeapFree(GetProcessHeap(), 0, key); } return index; @@ -403,9 +459,9 @@ static AsnInteger32 getItemAndInstanceFromTable(AsnObjectIdentifier *oid, AsnObjectIdentifier ipOid = { instanceLen, oid->ids + base->idLength + 1 };
- *instance = findValueInTable(&ipOid, table, tableEntrySize, - makeKey, compare) + 1; - if (*instance > table->numEntries) + *instance = findNextOidInTable(&ipOid, table, tableEntrySize, + makeKey, compare); + if (!*instance || *instance > table->numEntries) ret = SNMP_ERRORSTATUS_NOSUCHNAME; } } @@ -424,7 +480,7 @@ static AsnInteger32 getItemAndInstanceFromTable(AsnObjectIdentifier *oid, AsnObjectIdentifier ipOid = { instanceLen, oid->ids + base->idLength + 1 };
- *instance = findValueInTable(&ipOid, table, tableEntrySize, + *instance = findOidInTable(&ipOid, table, tableEntrySize, makeKey, compare); if (!*instance) ret = SNMP_ERRORSTATUS_NOSUCHNAME;