[MPlayer-dev-eng] [PATCH]libdvdread: seqfault and patch to fix it (again)
Frédéric Marchal
fmarchal at perso.be
Wed Sep 15 16:31:45 CEST 2010
Hello,
On July 11th, Morten Sjøgren reported a segfault due to the
double free of a buffer in ifoFree_PTL_MAIT and provided
a patch:
http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2010-July/066025.html
The patch was taken into account by Dominik 'Rathann' Mierzejewski
on September 2nd:
http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2010-September/066033.html
The patch is incomplete as ifoRead_PTL_MAIT can still return without
resetting the pointer in ifofile->ptl_mait. In my case, I have two
DVDs failing due an invalid seek offset passed to DVDFileSeek_().
The following patch set ifofile->ptl_mait to NULL (not 0 as in the
original patch) before every return statement.
Moreover, if the seek offset is obviously out of range, the loop over
the countries is interrupted and the nr_of_countries is set to the
index of the highest country that could be read. I'm not sure it is
the proper action but without a test case to disprove it, it sound
sensible as nr_of_countries doesn't seem to be used.
Frederic
---
Index: libdvdread4/ifo_read.c
===================================================================
--- libdvdread4/ifo_read.c (révision 1218)
+++ libdvdread4/ifo_read.c (copie de travail)
@@ -281,7 +281,8 @@ static void read_playback_type(playback_type_t *pt
static void free_ptl_mait(ptl_mait_t* ptl_mait, int num_entries) {
int i;
for (i = 0; i < num_entries; i++)
- free(ptl_mait->countries[i].pf_ptl_mai);
+ if (ptl_mait->countries[i].pf_ptl_mai)
+ free(ptl_mait->countries[i].pf_ptl_mai);
free(ptl_mait->countries);
free(ptl_mait);
@@ -1303,7 +1304,7 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
if(!(DVDReadBytes(ifofile->file, ptl_mait, PTL_MAIT_SIZE))) {
free(ptl_mait);
- ifofile->ptl_mait = 0;
+ ifofile->ptl_mait = NULL;
return 0;
}
@@ -1322,16 +1323,19 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
ptl_mait->countries = (ptl_mait_country_t *)malloc(info_length);
if(!ptl_mait->countries) {
free(ptl_mait);
- ifofile->ptl_mait = 0;
+ ifofile->ptl_mait = NULL;
return 0;
}
+ for(i = 0; i < ptl_mait->nr_of_countries; i++) {
+ ptl_mait->countries[i].pf_ptl_mai = NULL;
+ }
for(i = 0; i < ptl_mait->nr_of_countries; i++) {
if(!(DVDReadBytes(ifofile->file, &ptl_mait->countries[i], PTL_MAIT_COUNTRY_SIZE))) {
fprintf(stderr, "libdvdread: Unable to read PTL_MAIT.\n");
free(ptl_mait->countries);
free(ptl_mait);
- ifofile->ptl_mait = 0;
+ ifofile->ptl_mait = NULL;
return 0;
}
}
@@ -1351,24 +1355,39 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
for(i = 0; i < ptl_mait->nr_of_countries; i++) {
uint16_t *pf_temp;
+ if (ptl_mait->countries[i].pf_ptl_mai_start_byte
+ + 8*2 * (ptl_mait->nr_of_vtss + 1) > ptl_mait->last_byte + 1) {
+ fprintf(stderr, "libdvdread: should have %d countries but pointer to country %d is invalid.
\n",
+ ptl_mait->nr_of_countries, i);
+ /*
+ It may not be a good idea to truncate the number of countries at the first
+ invalid pointer. A test case is necessary to determine a more suitable
+ action.
+ */
+ ptl_mait->nr_of_countries=i;
+ break;
+ }
if(!DVDFileSeek_(ifofile->file,
ifofile->vmgi_mat->ptl_mait * DVD_BLOCK_LEN
+ ptl_mait->countries[i].pf_ptl_mai_start_byte)) {
- fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table.\n");
+ fprintf(stderr, "libdvdread: Unable to seek PTL_MAIT table at index %d.\n",i);
free(ptl_mait->countries);
free(ptl_mait);
+ ifofile->ptl_mait = NULL;
return 0;
}
info_length = (ptl_mait->nr_of_vtss + 1) * sizeof(pf_level_t);
pf_temp = (uint16_t *)malloc(info_length);
if(!pf_temp) {
free_ptl_mait(ptl_mait, i);
+ ifofile->ptl_mait = NULL;
return 0;
}
if(!(DVDReadBytes(ifofile->file, pf_temp, info_length))) {
- fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table.\n");
+ fprintf(stderr, "libdvdread: Unable to read PTL_MAIT table at index %d.\n",i);
free(pf_temp);
free_ptl_mait(ptl_mait, i);
+ ifofile->ptl_mait = NULL;
return 0;
}
for (j = 0; j < ((ptl_mait->nr_of_vtss + 1) * 8); j++) {
@@ -1378,6 +1397,7 @@ int ifoRead_PTL_MAIT(ifo_handle_t *ifofile) {
if(!ptl_mait->countries[i].pf_ptl_mai) {
free(pf_temp);
free_ptl_mait(ptl_mait, i);
+ ifofile->ptl_mait = NULL;
return 0;
}
{ /* Transpose the array so we can use C indexing. */
@@ -1402,7 +1422,8 @@ void ifoFree_PTL_MAIT(ifo_handle_t *ifofile) {
if(ifofile->ptl_mait) {
for(i = 0; i < ifofile->ptl_mait->nr_of_countries; i++) {
- free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
+ if (ifofile->ptl_mait->countries[i].pf_ptl_mai)
+ free(ifofile->ptl_mait->countries[i].pf_ptl_mai);
}
free(ifofile->ptl_mait->countries);
free(ifofile->ptl_mait);
More information about the MPlayer-dev-eng
mailing list