mirror of
				https://github.com/facebook/zstd.git
				synced 2025-10-31 08:37:43 +02:00 
			
		
		
		
	Merge pull request #1594 from terrelln/legacy-fix
[legacy] Fix Huffman jump table reads in v01 and v05
This commit is contained in:
		| @@ -1073,99 +1073,102 @@ static size_t HUF_decompress_usingDTable(   /* -3% slower when non static */ | ||||
|     const void* cSrc, size_t cSrcSize, | ||||
|     const U16* DTable) | ||||
| { | ||||
|     BYTE* const ostart = (BYTE*) dst; | ||||
|     BYTE* op = ostart; | ||||
|     BYTE* const omax = op + maxDstSize; | ||||
|     BYTE* const olimit = omax-15; | ||||
|  | ||||
|     const void* ptr = DTable; | ||||
|     const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1; | ||||
|     const U32 dtLog = DTable[0]; | ||||
|     size_t errorCode; | ||||
|     U32 reloadStatus; | ||||
|  | ||||
|     /* Init */ | ||||
|  | ||||
|     const U16* jumpTable = (const U16*)cSrc; | ||||
|     const size_t length1 = FSE_readLE16(jumpTable); | ||||
|     const size_t length2 = FSE_readLE16(jumpTable+1); | ||||
|     const size_t length3 = FSE_readLE16(jumpTable+2); | ||||
|     const size_t length4 = cSrcSize - 6 - length1 - length2 - length3;   // check coherency !! | ||||
|     const char* const start1 = (const char*)(cSrc) + 6; | ||||
|     const char* const start2 = start1 + length1; | ||||
|     const char* const start3 = start2 + length2; | ||||
|     const char* const start4 = start3 + length3; | ||||
|     FSE_DStream_t bitD1, bitD2, bitD3, bitD4; | ||||
|  | ||||
|     if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong; | ||||
|  | ||||
|     errorCode = FSE_initDStream(&bitD1, start1, length1); | ||||
|     if (FSE_isError(errorCode)) return errorCode; | ||||
|     errorCode = FSE_initDStream(&bitD2, start2, length2); | ||||
|     if (FSE_isError(errorCode)) return errorCode; | ||||
|     errorCode = FSE_initDStream(&bitD3, start3, length3); | ||||
|     if (FSE_isError(errorCode)) return errorCode; | ||||
|     errorCode = FSE_initDStream(&bitD4, start4, length4); | ||||
|     if (FSE_isError(errorCode)) return errorCode; | ||||
|  | ||||
|     reloadStatus=FSE_reloadDStream(&bitD2); | ||||
|  | ||||
|     /* 16 symbols per loop */ | ||||
|     for ( ; (reloadStatus<FSE_DStream_completed) && (op<olimit);  /* D2-3-4 are supposed to be synchronized and finish together */ | ||||
|         op+=16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1)) | ||||
|     if (cSrcSize < 6) return (size_t)-FSE_ERROR_srcSize_wrong; | ||||
|     { | ||||
| #define HUF_DECODE_SYMBOL_0(n, Dstream) \ | ||||
|         op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); | ||||
|         BYTE* const ostart = (BYTE*) dst; | ||||
|         BYTE* op = ostart; | ||||
|         BYTE* const omax = op + maxDstSize; | ||||
|         BYTE* const olimit = omax-15; | ||||
|  | ||||
| #define HUF_DECODE_SYMBOL_1(n, Dstream) \ | ||||
|         op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \ | ||||
|         if (FSE_32bits() && (HUF_MAX_TABLELOG>12)) FSE_reloadDStream(&Dstream) | ||||
|         const void* ptr = DTable; | ||||
|         const HUF_DElt* const dt = (const HUF_DElt*)(ptr)+1; | ||||
|         const U32 dtLog = DTable[0]; | ||||
|         size_t errorCode; | ||||
|         U32 reloadStatus; | ||||
|  | ||||
| #define HUF_DECODE_SYMBOL_2(n, Dstream) \ | ||||
|         op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \ | ||||
|         if (FSE_32bits()) FSE_reloadDStream(&Dstream) | ||||
|         /* Init */ | ||||
|  | ||||
|         HUF_DECODE_SYMBOL_1( 0, bitD1); | ||||
|         HUF_DECODE_SYMBOL_1( 1, bitD2); | ||||
|         HUF_DECODE_SYMBOL_1( 2, bitD3); | ||||
|         HUF_DECODE_SYMBOL_1( 3, bitD4); | ||||
|         HUF_DECODE_SYMBOL_2( 4, bitD1); | ||||
|         HUF_DECODE_SYMBOL_2( 5, bitD2); | ||||
|         HUF_DECODE_SYMBOL_2( 6, bitD3); | ||||
|         HUF_DECODE_SYMBOL_2( 7, bitD4); | ||||
|         HUF_DECODE_SYMBOL_1( 8, bitD1); | ||||
|         HUF_DECODE_SYMBOL_1( 9, bitD2); | ||||
|         HUF_DECODE_SYMBOL_1(10, bitD3); | ||||
|         HUF_DECODE_SYMBOL_1(11, bitD4); | ||||
|         HUF_DECODE_SYMBOL_0(12, bitD1); | ||||
|         HUF_DECODE_SYMBOL_0(13, bitD2); | ||||
|         HUF_DECODE_SYMBOL_0(14, bitD3); | ||||
|         HUF_DECODE_SYMBOL_0(15, bitD4); | ||||
|     } | ||||
|         const U16* jumpTable = (const U16*)cSrc; | ||||
|         const size_t length1 = FSE_readLE16(jumpTable); | ||||
|         const size_t length2 = FSE_readLE16(jumpTable+1); | ||||
|         const size_t length3 = FSE_readLE16(jumpTable+2); | ||||
|         const size_t length4 = cSrcSize - 6 - length1 - length2 - length3;   // check coherency !! | ||||
|         const char* const start1 = (const char*)(cSrc) + 6; | ||||
|         const char* const start2 = start1 + length1; | ||||
|         const char* const start3 = start2 + length2; | ||||
|         const char* const start4 = start3 + length3; | ||||
|         FSE_DStream_t bitD1, bitD2, bitD3, bitD4; | ||||
|  | ||||
|     if (reloadStatus!=FSE_DStream_completed)   /* not complete : some bitStream might be FSE_DStream_unfinished */ | ||||
|         return (size_t)-FSE_ERROR_corruptionDetected; | ||||
|         if (length1+length2+length3+6 >= cSrcSize) return (size_t)-FSE_ERROR_srcSize_wrong; | ||||
|  | ||||
|     /* tail */ | ||||
|     { | ||||
|         // bitTail = bitD1;   // *much* slower : -20% !??! | ||||
|         FSE_DStream_t bitTail; | ||||
|         bitTail.ptr = bitD1.ptr; | ||||
|         bitTail.bitsConsumed = bitD1.bitsConsumed; | ||||
|         bitTail.bitContainer = bitD1.bitContainer;   // required in case of FSE_DStream_endOfBuffer | ||||
|         bitTail.start = start1; | ||||
|         for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op<omax) ; op++) | ||||
|         errorCode = FSE_initDStream(&bitD1, start1, length1); | ||||
|         if (FSE_isError(errorCode)) return errorCode; | ||||
|         errorCode = FSE_initDStream(&bitD2, start2, length2); | ||||
|         if (FSE_isError(errorCode)) return errorCode; | ||||
|         errorCode = FSE_initDStream(&bitD3, start3, length3); | ||||
|         if (FSE_isError(errorCode)) return errorCode; | ||||
|         errorCode = FSE_initDStream(&bitD4, start4, length4); | ||||
|         if (FSE_isError(errorCode)) return errorCode; | ||||
|  | ||||
|         reloadStatus=FSE_reloadDStream(&bitD2); | ||||
|  | ||||
|         /* 16 symbols per loop */ | ||||
|         for ( ; (reloadStatus<FSE_DStream_completed) && (op<olimit);  /* D2-3-4 are supposed to be synchronized and finish together */ | ||||
|             op+=16, reloadStatus = FSE_reloadDStream(&bitD2) | FSE_reloadDStream(&bitD3) | FSE_reloadDStream(&bitD4), FSE_reloadDStream(&bitD1)) | ||||
|         { | ||||
|             HUF_DECODE_SYMBOL_0(0, bitTail); | ||||
|     #define HUF_DECODE_SYMBOL_0(n, Dstream) \ | ||||
|             op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); | ||||
|  | ||||
|     #define HUF_DECODE_SYMBOL_1(n, Dstream) \ | ||||
|             op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \ | ||||
|             if (FSE_32bits() && (HUF_MAX_TABLELOG>12)) FSE_reloadDStream(&Dstream) | ||||
|  | ||||
|     #define HUF_DECODE_SYMBOL_2(n, Dstream) \ | ||||
|             op[n] = HUF_decodeSymbol(&Dstream, dt, dtLog); \ | ||||
|             if (FSE_32bits()) FSE_reloadDStream(&Dstream) | ||||
|  | ||||
|             HUF_DECODE_SYMBOL_1( 0, bitD1); | ||||
|             HUF_DECODE_SYMBOL_1( 1, bitD2); | ||||
|             HUF_DECODE_SYMBOL_1( 2, bitD3); | ||||
|             HUF_DECODE_SYMBOL_1( 3, bitD4); | ||||
|             HUF_DECODE_SYMBOL_2( 4, bitD1); | ||||
|             HUF_DECODE_SYMBOL_2( 5, bitD2); | ||||
|             HUF_DECODE_SYMBOL_2( 6, bitD3); | ||||
|             HUF_DECODE_SYMBOL_2( 7, bitD4); | ||||
|             HUF_DECODE_SYMBOL_1( 8, bitD1); | ||||
|             HUF_DECODE_SYMBOL_1( 9, bitD2); | ||||
|             HUF_DECODE_SYMBOL_1(10, bitD3); | ||||
|             HUF_DECODE_SYMBOL_1(11, bitD4); | ||||
|             HUF_DECODE_SYMBOL_0(12, bitD1); | ||||
|             HUF_DECODE_SYMBOL_0(13, bitD2); | ||||
|             HUF_DECODE_SYMBOL_0(14, bitD3); | ||||
|             HUF_DECODE_SYMBOL_0(15, bitD4); | ||||
|         } | ||||
|  | ||||
|         if (FSE_endOfDStream(&bitTail)) | ||||
|             return op-ostart; | ||||
|         if (reloadStatus!=FSE_DStream_completed)   /* not complete : some bitStream might be FSE_DStream_unfinished */ | ||||
|             return (size_t)-FSE_ERROR_corruptionDetected; | ||||
|  | ||||
|         /* tail */ | ||||
|         { | ||||
|             // bitTail = bitD1;   // *much* slower : -20% !??! | ||||
|             FSE_DStream_t bitTail; | ||||
|             bitTail.ptr = bitD1.ptr; | ||||
|             bitTail.bitsConsumed = bitD1.bitsConsumed; | ||||
|             bitTail.bitContainer = bitD1.bitContainer;   // required in case of FSE_DStream_endOfBuffer | ||||
|             bitTail.start = start1; | ||||
|             for ( ; (FSE_reloadDStream(&bitTail) < FSE_DStream_completed) && (op<omax) ; op++) | ||||
|             { | ||||
|                 HUF_DECODE_SYMBOL_0(0, bitTail); | ||||
|             } | ||||
|  | ||||
|             if (FSE_endOfDStream(&bitTail)) | ||||
|                 return op-ostart; | ||||
|         } | ||||
|  | ||||
|         if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */ | ||||
|  | ||||
|         return (size_t)-FSE_ERROR_corruptionDetected; | ||||
|     } | ||||
|  | ||||
|     if (op==omax) return (size_t)-FSE_ERROR_dstSize_tooSmall;   /* dst buffer is full, but cSrc unfinished */ | ||||
|  | ||||
|     return (size_t)-FSE_ERROR_corruptionDetected; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -1998,91 +1998,92 @@ size_t HUFv05_decompress4X2_usingDTable( | ||||
|     const void* cSrc, size_t cSrcSize, | ||||
|     const U16* DTable) | ||||
| { | ||||
|     const BYTE* const istart = (const BYTE*) cSrc; | ||||
|     BYTE* const ostart = (BYTE*) dst; | ||||
|     BYTE* const oend = ostart + dstSize; | ||||
|     const void* const dtPtr = DTable; | ||||
|     const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1; | ||||
|     const U32 dtLog = DTable[0]; | ||||
|     size_t errorCode; | ||||
|  | ||||
|     /* Init */ | ||||
|     BITv05_DStream_t bitD1; | ||||
|     BITv05_DStream_t bitD2; | ||||
|     BITv05_DStream_t bitD3; | ||||
|     BITv05_DStream_t bitD4; | ||||
|     const size_t length1 = MEM_readLE16(istart); | ||||
|     const size_t length2 = MEM_readLE16(istart+2); | ||||
|     const size_t length3 = MEM_readLE16(istart+4); | ||||
|     size_t length4; | ||||
|     const BYTE* const istart1 = istart + 6;  /* jumpTable */ | ||||
|     const BYTE* const istart2 = istart1 + length1; | ||||
|     const BYTE* const istart3 = istart2 + length2; | ||||
|     const BYTE* const istart4 = istart3 + length3; | ||||
|     const size_t segmentSize = (dstSize+3) / 4; | ||||
|     BYTE* const opStart2 = ostart + segmentSize; | ||||
|     BYTE* const opStart3 = opStart2 + segmentSize; | ||||
|     BYTE* const opStart4 = opStart3 + segmentSize; | ||||
|     BYTE* op1 = ostart; | ||||
|     BYTE* op2 = opStart2; | ||||
|     BYTE* op3 = opStart3; | ||||
|     BYTE* op4 = opStart4; | ||||
|     U32 endSignal; | ||||
|  | ||||
|     /* Check */ | ||||
|     if (cSrcSize < 10) return ERROR(corruption_detected);   /* strict minimum : jump table + 1 byte per stream */ | ||||
|     { | ||||
|         const BYTE* const istart = (const BYTE*) cSrc; | ||||
|         BYTE* const ostart = (BYTE*) dst; | ||||
|         BYTE* const oend = ostart + dstSize; | ||||
|         const void* const dtPtr = DTable; | ||||
|         const HUFv05_DEltX2* const dt = ((const HUFv05_DEltX2*)dtPtr) +1; | ||||
|         const U32 dtLog = DTable[0]; | ||||
|         size_t errorCode; | ||||
|  | ||||
|     length4 = cSrcSize - (length1 + length2 + length3 + 6); | ||||
|     if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */ | ||||
|     errorCode = BITv05_initDStream(&bitD1, istart1, length1); | ||||
|     if (HUFv05_isError(errorCode)) return errorCode; | ||||
|     errorCode = BITv05_initDStream(&bitD2, istart2, length2); | ||||
|     if (HUFv05_isError(errorCode)) return errorCode; | ||||
|     errorCode = BITv05_initDStream(&bitD3, istart3, length3); | ||||
|     if (HUFv05_isError(errorCode)) return errorCode; | ||||
|     errorCode = BITv05_initDStream(&bitD4, istart4, length4); | ||||
|     if (HUFv05_isError(errorCode)) return errorCode; | ||||
|         /* Init */ | ||||
|         BITv05_DStream_t bitD1; | ||||
|         BITv05_DStream_t bitD2; | ||||
|         BITv05_DStream_t bitD3; | ||||
|         BITv05_DStream_t bitD4; | ||||
|         const size_t length1 = MEM_readLE16(istart); | ||||
|         const size_t length2 = MEM_readLE16(istart+2); | ||||
|         const size_t length3 = MEM_readLE16(istart+4); | ||||
|         size_t length4; | ||||
|         const BYTE* const istart1 = istart + 6;  /* jumpTable */ | ||||
|         const BYTE* const istart2 = istart1 + length1; | ||||
|         const BYTE* const istart3 = istart2 + length2; | ||||
|         const BYTE* const istart4 = istart3 + length3; | ||||
|         const size_t segmentSize = (dstSize+3) / 4; | ||||
|         BYTE* const opStart2 = ostart + segmentSize; | ||||
|         BYTE* const opStart3 = opStart2 + segmentSize; | ||||
|         BYTE* const opStart4 = opStart3 + segmentSize; | ||||
|         BYTE* op1 = ostart; | ||||
|         BYTE* op2 = opStart2; | ||||
|         BYTE* op3 = opStart3; | ||||
|         BYTE* op4 = opStart4; | ||||
|         U32 endSignal; | ||||
|  | ||||
|     /* 16-32 symbols per loop (4-8 symbols per stream) */ | ||||
|     endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4); | ||||
|     for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) { | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1); | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2); | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3); | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4); | ||||
|         HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1); | ||||
|         HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2); | ||||
|         HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3); | ||||
|         HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4); | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1); | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2); | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3); | ||||
|         HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4); | ||||
|         HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1); | ||||
|         HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2); | ||||
|         HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3); | ||||
|         HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4); | ||||
|         length4 = cSrcSize - (length1 + length2 + length3 + 6); | ||||
|         if (length4 > cSrcSize) return ERROR(corruption_detected);   /* overflow */ | ||||
|         errorCode = BITv05_initDStream(&bitD1, istart1, length1); | ||||
|         if (HUFv05_isError(errorCode)) return errorCode; | ||||
|         errorCode = BITv05_initDStream(&bitD2, istart2, length2); | ||||
|         if (HUFv05_isError(errorCode)) return errorCode; | ||||
|         errorCode = BITv05_initDStream(&bitD3, istart3, length3); | ||||
|         if (HUFv05_isError(errorCode)) return errorCode; | ||||
|         errorCode = BITv05_initDStream(&bitD4, istart4, length4); | ||||
|         if (HUFv05_isError(errorCode)) return errorCode; | ||||
|  | ||||
|         /* 16-32 symbols per loop (4-8 symbols per stream) */ | ||||
|         endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4); | ||||
|         for ( ; (endSignal==BITv05_DStream_unfinished) && (op4<(oend-7)) ; ) { | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1); | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2); | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3); | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4); | ||||
|             HUFv05_DECODE_SYMBOLX2_1(op1, &bitD1); | ||||
|             HUFv05_DECODE_SYMBOLX2_1(op2, &bitD2); | ||||
|             HUFv05_DECODE_SYMBOLX2_1(op3, &bitD3); | ||||
|             HUFv05_DECODE_SYMBOLX2_1(op4, &bitD4); | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op1, &bitD1); | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op2, &bitD2); | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op3, &bitD3); | ||||
|             HUFv05_DECODE_SYMBOLX2_2(op4, &bitD4); | ||||
|             HUFv05_DECODE_SYMBOLX2_0(op1, &bitD1); | ||||
|             HUFv05_DECODE_SYMBOLX2_0(op2, &bitD2); | ||||
|             HUFv05_DECODE_SYMBOLX2_0(op3, &bitD3); | ||||
|             HUFv05_DECODE_SYMBOLX2_0(op4, &bitD4); | ||||
|             endSignal = BITv05_reloadDStream(&bitD1) | BITv05_reloadDStream(&bitD2) | BITv05_reloadDStream(&bitD3) | BITv05_reloadDStream(&bitD4); | ||||
|         } | ||||
|  | ||||
|         /* check corruption */ | ||||
|         if (op1 > opStart2) return ERROR(corruption_detected); | ||||
|         if (op2 > opStart3) return ERROR(corruption_detected); | ||||
|         if (op3 > opStart4) return ERROR(corruption_detected); | ||||
|         /* note : op4 supposed already verified within main loop */ | ||||
|  | ||||
|         /* finish bitStreams one by one */ | ||||
|         HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); | ||||
|         HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); | ||||
|         HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); | ||||
|         HUFv05_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog); | ||||
|  | ||||
|         /* check */ | ||||
|         endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4); | ||||
|         if (!endSignal) return ERROR(corruption_detected); | ||||
|  | ||||
|         /* decoded size */ | ||||
|         return dstSize; | ||||
|     } | ||||
|  | ||||
|     /* check corruption */ | ||||
|     if (op1 > opStart2) return ERROR(corruption_detected); | ||||
|     if (op2 > opStart3) return ERROR(corruption_detected); | ||||
|     if (op3 > opStart4) return ERROR(corruption_detected); | ||||
|     /* note : op4 supposed already verified within main loop */ | ||||
|  | ||||
|     /* finish bitStreams one by one */ | ||||
|     HUFv05_decodeStreamX2(op1, &bitD1, opStart2, dt, dtLog); | ||||
|     HUFv05_decodeStreamX2(op2, &bitD2, opStart3, dt, dtLog); | ||||
|     HUFv05_decodeStreamX2(op3, &bitD3, opStart4, dt, dtLog); | ||||
|     HUFv05_decodeStreamX2(op4, &bitD4, oend,     dt, dtLog); | ||||
|  | ||||
|     /* check */ | ||||
|     endSignal = BITv05_endOfDStream(&bitD1) & BITv05_endOfDStream(&bitD2) & BITv05_endOfDStream(&bitD3) & BITv05_endOfDStream(&bitD4); | ||||
|     if (!endSignal) return ERROR(corruption_detected); | ||||
|  | ||||
|     /* decoded size */ | ||||
|     return dstSize; | ||||
| } | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user