dictionary_loader.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) Facebook, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under both the BSD-style license (found in the
  6. * LICENSE file in the root directory of this source tree) and the GPLv2 (found
  7. * in the COPYING file in the root directory of this source tree).
  8. * You may select, at your option, one of the above-listed licenses.
  9. */
  10. /**
  11. * This fuzz target makes sure that whenever a compression dictionary can be
  12. * loaded, the data can be round tripped.
  13. */
  14. #include <stddef.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include "fuzz_helpers.h"
  19. #include "zstd_helpers.h"
  20. #include "fuzz_data_producer.h"
  21. /**
  22. * Compresses the data and returns the compressed size or an error.
  23. */
  24. static size_t compress(void* compressed, size_t compressedCapacity,
  25. void const* source, size_t sourceSize,
  26. void const* dict, size_t dictSize,
  27. ZSTD_dictLoadMethod_e dictLoadMethod,
  28. ZSTD_dictContentType_e dictContentType,
  29. int const refPrefix)
  30. {
  31. ZSTD_CCtx* cctx = ZSTD_createCCtx();
  32. if (refPrefix)
  33. FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(
  34. cctx, dict, dictSize, dictContentType));
  35. else
  36. FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
  37. cctx, dict, dictSize, dictLoadMethod, dictContentType));
  38. size_t const compressedSize = ZSTD_compress2(
  39. cctx, compressed, compressedCapacity, source, sourceSize);
  40. ZSTD_freeCCtx(cctx);
  41. return compressedSize;
  42. }
  43. static size_t decompress(void* result, size_t resultCapacity,
  44. void const* compressed, size_t compressedSize,
  45. void const* dict, size_t dictSize,
  46. ZSTD_dictLoadMethod_e dictLoadMethod,
  47. ZSTD_dictContentType_e dictContentType,
  48. int const refPrefix)
  49. {
  50. ZSTD_DCtx* dctx = ZSTD_createDCtx();
  51. if (refPrefix)
  52. FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(
  53. dctx, dict, dictSize, dictContentType));
  54. else
  55. FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
  56. dctx, dict, dictSize, dictLoadMethod, dictContentType));
  57. size_t const resultSize = ZSTD_decompressDCtx(
  58. dctx, result, resultCapacity, compressed, compressedSize);
  59. FUZZ_ZASSERT(resultSize);
  60. ZSTD_freeDCtx(dctx);
  61. return resultSize;
  62. }
  63. int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
  64. {
  65. FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
  66. int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;
  67. ZSTD_dictLoadMethod_e const dlm =
  68. size = FUZZ_dataProducer_uint32Range(producer, 0, 1);
  69. ZSTD_dictContentType_e const dct =
  70. FUZZ_dataProducer_uint32Range(producer, 0, 2);
  71. size = FUZZ_dataProducer_remainingBytes(producer);
  72. DEBUGLOG(2, "Dict load method %d", dlm);
  73. DEBUGLOG(2, "Dict content type %d", dct);
  74. DEBUGLOG(2, "Dict size %u", (unsigned)size);
  75. void* const rBuf = FUZZ_malloc(size);
  76. size_t const cBufSize = ZSTD_compressBound(size);
  77. void* const cBuf = FUZZ_malloc(cBufSize);
  78. size_t const cSize =
  79. compress(cBuf, cBufSize, src, size, src, size, dlm, dct, refPrefix);
  80. /* compression failing is okay */
  81. if (ZSTD_isError(cSize)) {
  82. FUZZ_ASSERT_MSG(dct != ZSTD_dct_rawContent, "Raw must always succeed!");
  83. goto out;
  84. }
  85. size_t const rSize =
  86. decompress(rBuf, size, cBuf, cSize, src, size, dlm, dct, refPrefix);
  87. FUZZ_ASSERT_MSG(rSize == size, "Incorrect regenerated size");
  88. FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, rBuf, size), "Corruption!");
  89. out:
  90. free(cBuf);
  91. free(rBuf);
  92. FUZZ_dataProducer_free(producer);
  93. return 0;
  94. }