a9d1fb
Fix for CVE-2020-10001, which is a bug in the CUPS ippReadIO function when it
a9d1fb
reads tagged string values (nameWithLanguage and textWithLanguage).  The
a9d1fb
previous code verified that the length of the sub-strings (language identifier
a9d1fb
and name/text value) did not exceed the size of the allocated buffer (1 byte
a9d1fb
larger than the maximum IPP value size of 32767 bytes), but did not validate
a9d1fb
against the length of the actual IPP value.
a9d1fb
a9d1fb
The issues introduced by this vulnerability include:
a9d1fb
a9d1fb
- Potential information disclosure by copying uninitialized areas of memory into
a9d1fb
  an IPP string value.
a9d1fb
- Potential Denial of Service by supplying/using invalid string values when
a9d1fb
  strict validation has been disabled by the system administrator.
a9d1fb
a9d1fb
This change ensures that:
a9d1fb
a9d1fb
1. The language identifier does not extend beyond the end of the IPP value.
a9d1fb
2. The length of the name/text string is within the IPP value.
a9d1fb
3. The name/text string is within the IPP value.
a9d1fb
a9d1fb
diff --git a/cups/ipp.c b/cups/ipp.c
a9d1fb
index 3d529346c..adbb26fba 100644
a9d1fb
--- a/cups/ipp.c
a9d1fb
+++ b/cups/ipp.c
a9d1fb
@@ -2866,7 +2866,8 @@ ippReadIO(void       *src,		/* I - Data source */
a9d1fb
   unsigned char		*buffer,	/* Data buffer */
a9d1fb
 			string[IPP_MAX_TEXT],
a9d1fb
 					/* Small string buffer */
a9d1fb
-			*bufptr;	/* Pointer into buffer */
a9d1fb
+			*bufptr,	/* Pointer into buffer */
a9d1fb
+			*bufend;	/* End of buffer */
a9d1fb
   ipp_attribute_t	*attr;		/* Current attribute */
a9d1fb
   ipp_tag_t		tag;		/* Current tag */
a9d1fb
   ipp_tag_t		value_tag;	/* Current value tag */
a9d1fb
@@ -3441,6 +3442,7 @@ ippReadIO(void       *src,		/* I - Data source */
a9d1fb
 		}
a9d1fb
a9d1fb
                 bufptr = buffer;
a9d1fb
+                bufend = buffer + n;
a9d1fb
a9d1fb
 	       /*
a9d1fb
 	        * text-with-language and name-with-language are composite
a9d1fb
@@ -3454,7 +3456,7 @@ ippReadIO(void       *src,		/* I - Data source */
a9d1fb
a9d1fb
 		n = (bufptr[0] << 8) | bufptr[1];
a9d1fb
a9d1fb
-		if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE) || n >= (int)sizeof(string))
a9d1fb
+		if ((bufptr + 2 + n + 2) > bufend || n >= (int)sizeof(string))
a9d1fb
 		{
a9d1fb
 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
a9d1fb
 		                _("IPP language length overflows value."), 1);
a9d1fb
@@ -3481,7 +3483,7 @@ ippReadIO(void       *src,		/* I - Data source */
a9d1fb
                 bufptr += 2 + n;
a9d1fb
 		n = (bufptr[0] << 8) | bufptr[1];
a9d1fb
a9d1fb
-		if ((bufptr + 2 + n) >= (buffer + IPP_BUF_SIZE))
a9d1fb
+		if ((bufptr + 2 + n) > bufend)
a9d1fb
 		{
a9d1fb
 		  _cupsSetError(IPP_STATUS_ERROR_INTERNAL,
a9d1fb
 		                _("IPP string length overflows value."), 1);
a9d1fb