You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

232 lines
5.6 KiB

  1. /*
  2. * Compression handling functions
  3. *
  4. * Copyright (C) 2008-2019, Joachim Metz <joachim.metz@gmail.com>
  5. *
  6. * Refer to AUTHORS for acknowledgements.
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU Lesser General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. */
  21. #include <common.h>
  22. #include <types.h>
  23. #if defined( HAVE_STDLIB_H ) || defined( WINAPI )
  24. #include <stdlib.h>
  25. #endif
  26. #if defined( HAVE_ZLIB ) || defined( ZLIB_DLL )
  27. #include <zlib.h>
  28. #endif
  29. #include "libpff_compression.h"
  30. #include "libpff_definitions.h"
  31. #include "libpff_deflate.h"
  32. #include "libpff_libcerror.h"
  33. #include "libpff_libcnotify.h"
  34. /* Decompresses data using the compression method
  35. * Returns 1 on success, 0 on failure or -1 on error
  36. */
  37. int libpff_decompress_data(
  38. const uint8_t *compressed_data,
  39. size_t compressed_data_size,
  40. uint16_t compression_method,
  41. uint8_t *uncompressed_data,
  42. size_t *uncompressed_data_size,
  43. libcerror_error_t **error )
  44. {
  45. static char *function = "libpff_decompress_data";
  46. int result = 0;
  47. #if ( defined( HAVE_ZLIB ) && defined( HAVE_ZLIB_UNCOMPRESS ) ) || defined( ZLIB_DLL )
  48. uLongf zlib_uncompressed_data_size = 0;
  49. #endif
  50. if( compressed_data == NULL )
  51. {
  52. libcerror_error_set(
  53. error,
  54. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  55. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  56. "%s: invalid compressed data buffer.",
  57. function );
  58. return( -1 );
  59. }
  60. if( uncompressed_data == NULL )
  61. {
  62. libcerror_error_set(
  63. error,
  64. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  65. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  66. "%s: invalid uncompressed data buffer.",
  67. function );
  68. return( -1 );
  69. }
  70. if( uncompressed_data == compressed_data )
  71. {
  72. libcerror_error_set(
  73. error,
  74. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  75. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  76. "%s: invalid compressed data buffer equals uncompressed data buffer.",
  77. function );
  78. return( -1 );
  79. }
  80. if( uncompressed_data_size == NULL )
  81. {
  82. libcerror_error_set(
  83. error,
  84. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  85. LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
  86. "%s: invalid uncompressed data size.",
  87. function );
  88. return( -1 );
  89. }
  90. if( compression_method == LIBPFF_COMPRESSION_METHOD_DEFLATE )
  91. {
  92. #if ( defined( HAVE_ZLIB ) && defined( HAVE_ZLIB_UNCOMPRESS ) ) || defined( ZLIB_DLL )
  93. if( compressed_data_size > (size_t) ULONG_MAX )
  94. {
  95. libcerror_error_set(
  96. error,
  97. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  98. LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
  99. "%s: invalid compressed data size value exceeds maximum.",
  100. function );
  101. return( -1 );
  102. }
  103. if( *uncompressed_data_size > (size_t) ULONG_MAX )
  104. {
  105. libcerror_error_set(
  106. error,
  107. LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
  108. LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
  109. "%s: invalid uncompressed data size value exceeds maximum.",
  110. function );
  111. return( -1 );
  112. }
  113. zlib_uncompressed_data_size = (uLongf) *uncompressed_data_size;
  114. result = uncompress(
  115. (Bytef *) uncompressed_data,
  116. &zlib_uncompressed_data_size,
  117. (Bytef *) compressed_data,
  118. (uLong) compressed_data_size );
  119. if( result == Z_OK )
  120. {
  121. *uncompressed_data_size = (size_t) zlib_uncompressed_data_size;
  122. result = 1;
  123. }
  124. else if( result == Z_DATA_ERROR )
  125. {
  126. #if defined( HAVE_DEBUG_OUTPUT )
  127. if( libcnotify_verbose != 0 )
  128. {
  129. libcnotify_printf(
  130. "%s: unable to read compressed data: data error.\n",
  131. function );
  132. }
  133. #endif
  134. *uncompressed_data_size = 0;
  135. result = -1;
  136. }
  137. else if( result == Z_BUF_ERROR )
  138. {
  139. #if defined( HAVE_DEBUG_OUTPUT )
  140. if( libcnotify_verbose != 0 )
  141. {
  142. libcnotify_printf(
  143. "%s: unable to read compressed data: target buffer too small.\n",
  144. function );
  145. }
  146. #endif
  147. /* Estimate that a factor 2 enlargement should suffice
  148. */
  149. *uncompressed_data_size *= 2;
  150. result = 0;
  151. }
  152. else if( result == Z_MEM_ERROR )
  153. {
  154. libcerror_error_set(
  155. error,
  156. LIBCERROR_ERROR_DOMAIN_MEMORY,
  157. LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
  158. "%s: unable to read compressed data: insufficient memory.",
  159. function );
  160. *uncompressed_data_size = 0;
  161. result = -1;
  162. }
  163. else
  164. {
  165. libcerror_error_set(
  166. error,
  167. LIBCERROR_ERROR_DOMAIN_COMPRESSION,
  168. LIBCERROR_COMPRESSION_ERROR_DECOMPRESS_FAILED,
  169. "%s: zlib returned undefined error: %d.",
  170. function,
  171. result );
  172. *uncompressed_data_size = 0;
  173. result = -1;
  174. }
  175. #else
  176. result = libpff_deflate_decompress(
  177. compressed_data,
  178. compressed_data_size,
  179. uncompressed_data,
  180. uncompressed_data_size,
  181. error );
  182. if( result != 1 )
  183. {
  184. libcerror_error_set(
  185. error,
  186. LIBCERROR_ERROR_DOMAIN_ENCRYPTION,
  187. LIBCERROR_ENCRYPTION_ERROR_GENERIC,
  188. "%s: unable to decompress deflate compressed data.",
  189. function );
  190. return( -1 );
  191. }
  192. #endif /* ( defined( HAVE_ZLIB ) && defined( HAVE_ZLIB_UNCOMPRESS ) ) || defined( ZLIB_DLL ) */
  193. }
  194. else
  195. {
  196. libcerror_error_set(
  197. error,
  198. LIBCERROR_ERROR_DOMAIN_RUNTIME,
  199. LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
  200. "%s: unsupported compression method.",
  201. function );
  202. return( -1 );
  203. }
  204. return( result );
  205. }