Browse code

handle E2BIG correctly, avoid infinite loops on iconv errors. (bb #785)

git-svn: trunk@3525

Török Edvin authored on 2008/01/23 02:12:12
Showing 2 changed files
... ...
@@ -1,3 +1,8 @@
1
+Tue Jan 22 18:47:54 EET 2008 (edwin)
2
+-----------------------------------
3
+  * libclamav/entconv.c: handle E2BIG correctly, avoid infinite loops on iconv
4
+  errors. (bb #785)
5
+
1 6
 Tue Jan 22 15:29:15 CET 2008 (tk)
2 7
 ---------------------------------
3 8
   * configure: if available use dscl on Mac OS X (bb#753)
... ...
@@ -850,6 +850,7 @@ static int in_iconv_u16(m_area_t* in_m_area, iconv_t* iconv_struct, m_area_t* ou
850 850
 	if(!inleft) {
851 851
 		/* EOF */
852 852
 		out_m_area->offset = out_m_area->length = 0;
853
+		return 0;
853 854
 	}
854 855
 	/* convert encoding conv->tmp_area. conv->out_area */
855 856
 	alignfix = inleft%4;/* iconv gives an error if we give him 3 bytes to convert, 
... ...
@@ -864,21 +865,31 @@ static int in_iconv_u16(m_area_t* in_m_area, iconv_t* iconv_struct, m_area_t* ou
864 864
 		inleft = 4;
865 865
 	}
866 866
 
867
-	rc = (size_t)-1;
868
-	while (inleft && (outleft >= 2) && rc == (size_t)-1) { /* iconv doesn't like inleft to be 0 */
867
+	while (inleft && (outleft >= 2)) { /* iconv doesn't like inleft to be 0 */
868
+		const size_t outleft_last = outleft;
869 869
 		assert(*iconv_struct != (iconv_t)-1);
870 870
 		rc = iconv(*iconv_struct, (char**) &input,  &inleft, (char**) &out, &outleft);
871
-		if(rc == (size_t)-1 && errno != E2BIG) {
872
-			cli_dbgmsg("iconv error:%s, silently resuming (%lu, %lu, %ld, %ld)\n",
873
-					strerror(errno), inleft, outleft, input - (char*)in_m_area->buffer,
874
-					out - (char*)out_m_area->buffer);
875
-			/* output raw byte, and resume at next byte */
876
-			if(outleft < 2) break;
877
-			outleft -= 2;
878
-			*out++ = 0;
879
-			*out++ = *input++;
880
-			inleft--;
871
+		if(rc == (size_t)-1) {
872
+			if(errno == E2BIG) {
873
+				/* not enough space in output buffer */
874
+				break;
875
+			}
876
+			cli_dbgmsg(MODULE_NAME "iconv error:%s\n", strerror(errno));
877
+		} else if(outleft == outleft_last) {
878
+			cli_dbgmsg(MODULE_NAME "iconv stall (no output)\n");
879
+		} else {
880
+			/* everything ok */
881
+			continue;
881 882
 		}
883
+		cli_dbgmsg(MODULE_NAME "resuming (inleft:%lu, outleft:%lu, inpos:%ld, %ld)\n",
884
+					inleft, outleft, input - (char*)in_m_area->buffer,
885
+					out - (char*)out_m_area->buffer);
886
+		/* output raw byte, and resume at next byte */
887
+		if(outleft < 2) break;
888
+		outleft -= 2;
889
+		*out++ = 0;
890
+		*out++ = *input++;
891
+		inleft--;
882 892
 	}
883 893
 	in_m_area->offset = in_m_area->length - inleft;
884 894
 	if(out_m_area->length >= 0 && out_m_area->length >= (off_t)outleft) {