[libbdplus-devel] [Git][videolan/libbdplus][master] 7 commits: Fix leak
Petri Hintukainen (@hpi)
gitlab at videolan.org
Sat Oct 2 18:57:28 UTC 2021
Petri Hintukainen pushed to branch master at VideoLAN / libbdplus
Commits:
072544fb by anonymous at 2021-10-02T21:51:57+03:00
Fix leak
- - - - -
76425cfe by anonymous at 2021-10-02T21:52:03+03:00
Fix crash when freeing incomplete tables
- - - - -
c89a9f3b by anonymous at 2021-10-02T21:53:36+03:00
segment_setTable(): fix possible integer overflows on invalid input
- - - - -
de4beece by anonymous at 2021-10-02T21:54:11+03:00
segment_setTable(): Fix error handling
- - - - -
3d4a541e by anonymous at 2021-10-02T21:55:38+03:00
Simplify
- - - - -
2a50ad56 by anonymous at 2021-10-02T21:56:05+03:00
segment_setTable(): sanity check table size
- - - - -
308c4784 by anonymous at 2021-10-02T21:56:55+03:00
segment_setTable(): check for input buffer overflow (read)
- - - - -
1 changed file:
- src/libbdplus/bdsvm/segment.c
Changes:
=====================================
src/libbdplus/bdsvm/segment.c
=====================================
@@ -97,7 +97,7 @@ typedef struct entry_s entry_t;
struct segment_s {
uint32_t encrypted;
- uint32_t offset;
+ //uint32_t offset;
uint32_t numEntries;
entry_t *Entries;
@@ -169,7 +169,7 @@ uint32_t segment_numEntries(conv_table_t *ct)
int32_t segment_setTable(conv_table_t **conv_tab, uint8_t *Table, uint32_t len)
{
- uint32_t numTables, table, currseg, currentry;
+ uint32_t table, currseg, currentry;
uint32_t tmp;
conv_table_t *ct;
subtable_t *subtable;
@@ -179,35 +179,23 @@ int32_t segment_setTable(conv_table_t **conv_tab, uint8_t *Table, uint32_t len)
uint32_t offset = 0;
uint32_t encrypted_segments = 0;
- if (!Table || !len) return -1;
+ if (!Table || len < 2) return -1;
+ if (len > 0x400000) return -1; /* VM memory size */
BD_DEBUG(DBG_BDPLUS,"[segment] Starting decode of conv_tab.bin: %p (%d)\n", Table, len);
- ct = *conv_tab;
-
-
- // If we do not already have a conv_tab, allocate it.
- if (!ct) {
-
- ct = (conv_table_t *) malloc(sizeof(*ct));
- if (!ct) return -2;
-
- memset(ct, 0, sizeof(*ct));
-
- *conv_tab = ct;
-
+ if (*conv_tab) {
+ BD_DEBUG(DBG_BDPLUS|DBG_CRIT,"[segment] ERROR: Table already exists.\n");
+ return -1;
}
+ ct = (conv_table_t *) calloc(1, sizeof(*ct));
+ if (!ct) return -2;
- // Update the number of tables we received
- numTables = FETCHU2(&Table[ptr]);
-
- if (ct->numTables && (ct->numTables != numTables)) {
- BD_DEBUG(DBG_BDPLUS,"[segment] Warning, numTables changed between conv_tab parts!\n");
- }
- ct->numTables = numTables;
+ // Update the number of tables we received
+ ct->numTables = FETCHU2(&Table[ptr]);
ptr += 2;
// Let nextSegment() initialise these, So that we can ignore
@@ -215,72 +203,52 @@ int32_t segment_setTable(conv_table_t **conv_tab, uint8_t *Table, uint32_t len)
ct->current_table = 0xffffffff;
ct->current_segment = 0xffffffff;
- // Allocate area to hold all subtable structs, if not already allocated
- if (!ct->Tables) {
- ct->Tables = (subtable_t *) malloc(sizeof(subtable_t) * ct->numTables);
- if (!ct->Tables) return segment_freeTable(conv_tab);
- memset(ct->Tables,
- 0, sizeof(subtable_t) * numTables);
- }
+ ct->Tables = (subtable_t *) calloc(ct->numTables, sizeof(subtable_t));
+ if (!ct->Tables) goto error;
+
+ BD_DEBUG(DBG_BDPLUS,"[segment] num tables %d\n", ct->numTables);
- BD_DEBUG(DBG_BDPLUS,"[segment] num tables %d\n", numTables);
+ for (table = 0; table < ct->numTables; table++) {
- for (table = 0; table < numTables; table++) {
- uint32_t tableID;
- uint32_t numSegments;
+ if (len < 6 || ptr > len - 6)
+ goto error;
// Assign pointer so we don't need to keep dereferencing
subtable = &ct->Tables[ table ];
- tableID = FETCH4(&Table[ptr]);
+ subtable->tableID = FETCH4(&Table[ptr]);
ptr += 4;
- if (subtable->tableID && (subtable->tableID != tableID)) {
- BD_DEBUG(DBG_BDPLUS,"[segment] Warning: tableID changed %08X != %08X\n",
- subtable->tableID, tableID);
- }
- subtable->tableID = tableID;
-
// Here, we might increase the number of segments.
- //subtable->numSegments = FETCHU2(&Table[ptr]);
- numSegments = FETCHU2(&Table[ptr]);
+ subtable->numSegments = FETCHU2(&Table[ptr]);
ptr += 2;
// Don't allocate if no (new) segments
- if (!numSegments) continue;
-
- if (subtable->numSegments && (subtable->numSegments != numSegments)) {
- BD_DEBUG(DBG_BDPLUS,"[segment] Warning: numSegments changed %08X != %08X\n",
- subtable->numSegments, numSegments);
- }
-
- subtable->numSegments = numSegments;
+ if (!subtable->numSegments) continue;
BD_DEBUG(DBG_BDPLUS,"[segment] Table %d ID %08X, %u segments\n",
table, subtable->tableID, subtable->numSegments);
- // Allocate area if required
- if (!subtable->Segments) {
- subtable->Segments = (segment_t *) malloc(sizeof(segment_t) *
- numSegments);
- if (!subtable->Segments) continue;
- memset(subtable->Segments, 0,
- sizeof(segment_t) *
- numSegments);
- }
-
+ subtable->Segments = (segment_t *) calloc(subtable->numSegments, sizeof(segment_t));
+ if (!subtable->Segments) goto error;
// Loop on all segments
for (currseg = 0;
- currseg < numSegments;
+ currseg < subtable->numSegments;
currseg++) {
+ if (ptr + currseg * 4 > len - 4)
+ goto error;
+
segment = &subtable->Segments[ currseg ];
offset = FETCH4(&Table[ptr + (currseg * 4) ]);
- segment->offset = offset; // not really used
+ //segment->offset = offset; // not really used
+
+ if (offset > len - 4)
+ goto error;
segment->numEntries = FETCH4(&Table[offset]);
offset += 4;
@@ -291,19 +259,19 @@ int32_t segment_setTable(conv_table_t **conv_tab, uint8_t *Table, uint32_t len)
BD_DEBUG(DBG_BDPLUS," Segment %d offset %08X -> %d entries\n",
currseg, offset-4, segment->numEntries);
- segment->Entries = (entry_t *) malloc(sizeof(entry_t) *
- segment->numEntries);
- if (!segment->Entries) continue;
+ segment->Entries = (entry_t *) calloc(segment->numEntries, sizeof(entry_t));
+ if (!segment->Entries) goto error;
// If we have non-zero entries, assume they are encrypted
segment->encrypted = 1;
encrypted_segments++;
- memset(segment->Entries, 0, sizeof(entry_t) *
- segment->numEntries);
-
// First read in the index table
for (currentry = 0; currentry < segment->numEntries; currentry++) {
+
+ if (offset > len - 4)
+ goto error;
+
entry = &segment->Entries[ currentry ];
entry->index = FETCH4(&Table[offset]);
@@ -314,6 +282,9 @@ int32_t segment_setTable(conv_table_t **conv_tab, uint8_t *Table, uint32_t len)
for (currentry = 0; currentry < segment->numEntries; currentry++) {
entry = &segment->Entries[ currentry ];
+ if (len < 16 || offset > len - 16)
+ goto error;
+
entry->flags = Table[ offset ];
offset += 1;
@@ -345,7 +316,13 @@ int32_t segment_setTable(conv_table_t **conv_tab, uint8_t *Table, uint32_t len)
BD_DEBUG(DBG_BDPLUS,"[segments] Done parsing. %d segments need decrypting.\n",
encrypted_segments);
+ *conv_tab = ct;
return ct->numTables;
+
+ error:
+ BD_DEBUG(DBG_BDPLUS|DBG_CRIT,"[segments] Conversion table parsing failed.\n");
+ segment_freeTable(&ct);
+ return -1;
}
@@ -361,11 +338,13 @@ int32_t segment_freeTable(conv_table_t **Table)
ct = *Table;
+ if (ct->Tables)
for (table = 0; table < ct->numTables; table++) {
// Assign pointer so we don't need to keep dereferencing
subtable = &ct->Tables[ table ];
+ if (subtable->Segments)
for (currseg = 0; currseg < subtable->numSegments; currseg++) {
segment = &subtable->Segments[ currseg ];
@@ -383,6 +362,8 @@ int32_t segment_freeTable(conv_table_t **Table)
X_FREE(ct->Tables);
ct->numTables = 0;
+ X_FREE(ct);
+
*Table = NULL;
return 0;
View it on GitLab: https://code.videolan.org/videolan/libbdplus/-/compare/001e81d9c4057e8375e5a6ca06b0ce99c72f76d4...308c47848f855d207e06e5e0982c18c3ffcf5120
--
View it on GitLab: https://code.videolan.org/videolan/libbdplus/-/compare/001e81d9c4057e8375e5a6ca06b0ce99c72f76d4...308c47848f855d207e06e5e0982c18c3ffcf5120
You're receiving this email because of your account on code.videolan.org.
More information about the libbdplus-devel
mailing list