raw_dictionary_round_trip.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /*
  2. * Copyright (c) 2016-2021, 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 performs a zstd round-trip test (compress & decompress) with
  12. * a raw content dictionary, compares the result with the original, and calls
  13. * abort() on corruption.
  14. */
  15. #include <stddef.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <string.h>
  19. #include "fuzz_helpers.h"
  20. #include "zstd_helpers.h"
  21. #include "fuzz_data_producer.h"
  22. static ZSTD_CCtx *cctx = NULL;
  23. static ZSTD_DCtx *dctx = NULL;
  24. static size_t roundTripTest(void *result, size_t resultCapacity,
  25. void *compressed, size_t compressedCapacity,
  26. const void *src, size_t srcSize,
  27. const void *dict, size_t dictSize,
  28. FUZZ_dataProducer_t *producer)
  29. {
  30. ZSTD_dictContentType_e const dictContentType = ZSTD_dct_rawContent;
  31. int const refPrefix = FUZZ_dataProducer_uint32Range(producer, 0, 1) != 0;
  32. size_t cSize;
  33. FUZZ_setRandomParameters(cctx, srcSize, producer);
  34. /* Disable checksum so we can use sizes smaller than compress bound. */
  35. FUZZ_ZASSERT(ZSTD_CCtx_setParameter(cctx, ZSTD_c_checksumFlag, 0));
  36. if (refPrefix)
  37. FUZZ_ZASSERT(ZSTD_CCtx_refPrefix_advanced(
  38. cctx, dict, dictSize,
  39. ZSTD_dct_rawContent));
  40. else
  41. FUZZ_ZASSERT(ZSTD_CCtx_loadDictionary_advanced(
  42. cctx, dict, dictSize,
  43. (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
  44. ZSTD_dct_rawContent));
  45. cSize = ZSTD_compress2(cctx, compressed, compressedCapacity, src, srcSize);
  46. FUZZ_ZASSERT(cSize);
  47. if (refPrefix)
  48. FUZZ_ZASSERT(ZSTD_DCtx_refPrefix_advanced(
  49. dctx, dict, dictSize,
  50. dictContentType));
  51. else
  52. FUZZ_ZASSERT(ZSTD_DCtx_loadDictionary_advanced(
  53. dctx, dict, dictSize,
  54. (ZSTD_dictLoadMethod_e)FUZZ_dataProducer_uint32Range(producer, 0, 1),
  55. dictContentType));
  56. {
  57. size_t const ret = ZSTD_decompressDCtx(
  58. dctx, result, resultCapacity, compressed, cSize);
  59. return ret;
  60. }
  61. }
  62. int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
  63. {
  64. /* Give a random portion of src data to the producer, to use for
  65. parameter generation. The rest will be used for (de)compression */
  66. FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
  67. size = FUZZ_dataProducer_reserveDataPrefix(producer);
  68. uint8_t const* const srcBuf = src;
  69. size_t const srcSize = FUZZ_dataProducer_uint32Range(producer, 0, size);
  70. uint8_t const* const dictBuf = srcBuf + srcSize;
  71. size_t const dictSize = size - srcSize;
  72. size_t const decompSize = srcSize;
  73. void* const decompBuf = FUZZ_malloc(decompSize);
  74. size_t compSize = ZSTD_compressBound(srcSize);
  75. void* compBuf;
  76. /* Half of the time fuzz with a 1 byte smaller output size.
  77. * This will still succeed because we force the checksum to be disabled,
  78. * giving us 4 bytes of overhead.
  79. */
  80. compSize -= FUZZ_dataProducer_uint32Range(producer, 0, 1);
  81. compBuf = FUZZ_malloc(compSize);
  82. if (!cctx) {
  83. cctx = ZSTD_createCCtx();
  84. FUZZ_ASSERT(cctx);
  85. }
  86. if (!dctx) {
  87. dctx = ZSTD_createDCtx();
  88. FUZZ_ASSERT(dctx);
  89. }
  90. {
  91. size_t const result =
  92. roundTripTest(decompBuf, decompSize, compBuf, compSize, srcBuf, srcSize, dictBuf, dictSize, producer);
  93. FUZZ_ZASSERT(result);
  94. FUZZ_ASSERT_MSG(result == srcSize, "Incorrect regenerated size");
  95. FUZZ_ASSERT_MSG(!FUZZ_memcmp(src, decompBuf, srcSize), "Corruption!");
  96. }
  97. free(decompBuf);
  98. free(compBuf);
  99. FUZZ_dataProducer_free(producer);
  100. #ifndef STATEFUL_FUZZING
  101. ZSTD_freeCCtx(cctx); cctx = NULL;
  102. ZSTD_freeDCtx(dctx); dctx = NULL;
  103. #endif
  104. return 0;
  105. }