changeset 14164:5901a6392db3

Security fixes ported from upstream (xine)
author rtognimp
date Wed, 15 Dec 2004 21:27:14 +0000
parents dd835e8f3698
children 0846071c22cb
files libmpdemux/pnm.c
diffstat 1 files changed, 26 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libmpdemux/pnm.c	Wed Dec 15 19:12:46 2004 +0000
+++ b/libmpdemux/pnm.c	Wed Dec 15 21:27:14 2004 +0000
@@ -307,9 +307,12 @@
                          char *data, int *need_response) {
 
   unsigned int chunk_size;
-  int n;
+  unsigned int n;
   char *ptr;
  
+  if (max < PREAMBLE_SIZE)
+    return -1;
+
   /* get first PREAMBLE_SIZE bytes and ignore checksum */
   rm_read (p->s, data, CHECKSUM_SIZE);
   if (data[0] == 0x72)
@@ -317,6 +320,8 @@
   else
     rm_read (p->s, data+CHECKSUM_SIZE, PREAMBLE_SIZE-CHECKSUM_SIZE);
   
+  max -= PREAMBLE_SIZE;
+
   *chunk_type = BE_32(data);
   chunk_size = BE_32(data+4);
 
@@ -324,18 +329,30 @@
     case PNA_TAG:
       *need_response=0;
       ptr=data+PREAMBLE_SIZE;
+      if (max < 1)
+	return -1;
       rm_read (p->s, ptr++, 1);
+      max -= 1;
 
       while(1) {
 	/* expecting following chunk format: 0x4f <chunk size> <data...> */
 
+        if (max < 2)
+          return -1;
         rm_read (p->s, ptr, 2);
+        max -= 2;
 	if (*ptr == 'X') /* checking for server message */
 	{
 	  printf("input_pnm: got a message from server:\n");
+	  if (max < 1)
+	    return -1;
 	  rm_read (p->s, ptr+2, 1);
+	  max = -1;
 	  n=BE_16(ptr+1);
+	  if (max < n)
+	    return -1;
 	  rm_read (p->s, ptr+3, n);
+	  max -= n;
 	  ptr[3+n]=0;
 	  printf("%s\n",ptr+3);
 	  return -1;
@@ -354,10 +371,15 @@
 	}
 	if (*ptr != 0x4f) break;
 	n=ptr[1];
+	if (max < n)
+	  return -1;
 	rm_read (p->s, ptr+2, n);
+	max -= n;
 	ptr+=(n+2);
       }
       /* the checksum of the next chunk is ignored here */
+      if (max < 1)
+        return -1;
       rm_read (p->s, ptr+2, 1);
       ptr+=3;
       chunk_size=ptr-data;
@@ -367,10 +389,12 @@
     case PROP_TAG:
     case MDPR_TAG:
     case CONT_TAG:
-      if (chunk_size > max) {
+      if (chunk_size > max || chunk_size < PREAMBLE_SIZE) {
         printf("error: max chunk size exeeded (max was 0x%04x)\n", max);
+#ifdef LOG
         n=rm_read (p->s, &data[PREAMBLE_SIZE], 0x100 - PREAMBLE_SIZE);
         hexdump(data,n+PREAMBLE_SIZE);
+#endif
         return -1;
       }
       rm_read (p->s, &data[PREAMBLE_SIZE], chunk_size-PREAMBLE_SIZE);