fse_read_ncount.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  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 round trips the FSE normalized count with FSE_writeNCount()
  12. * and FSE_readNcount() to ensure that it can always round trip correctly.
  13. */
  14. #define FSE_STATIC_LINKING_ONLY
  15. #define ZSTD_STATIC_LINKING_ONLY
  16. #include <stddef.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include "fuzz_helpers.h"
  21. #include "zstd_helpers.h"
  22. #include "fuzz_data_producer.h"
  23. #include "fse.h"
  24. int LLVMFuzzerTestOneInput(const uint8_t *src, size_t size)
  25. {
  26. FUZZ_dataProducer_t *producer = FUZZ_dataProducer_create(src, size);
  27. /* Pick a random tableLog and maxSymbolValue */
  28. unsigned const tableLog = FUZZ_dataProducer_uint32Range(producer, FSE_MIN_TABLELOG, FSE_MAX_TABLELOG);
  29. unsigned const maxSymbolValue = FUZZ_dataProducer_uint32Range(producer, 0, 255);
  30. unsigned remainingWeight = (1u << tableLog) - 1;
  31. size_t dataSize;
  32. BYTE data[512];
  33. short ncount[256];
  34. /* Randomly fill the normalized count */
  35. memset(ncount, 0, sizeof(ncount));
  36. {
  37. unsigned s;
  38. for (s = 0; s < maxSymbolValue && remainingWeight > 0; ++s) {
  39. short n = (short)FUZZ_dataProducer_int32Range(producer, -1, remainingWeight);
  40. ncount[s] = n;
  41. if (n < 0) {
  42. remainingWeight -= 1;
  43. } else {
  44. assert((unsigned)n <= remainingWeight);
  45. remainingWeight -= n;
  46. }
  47. }
  48. /* Ensure ncount[maxSymbolValue] != 0 and the sum is (1<<tableLog) */
  49. ncount[maxSymbolValue] = remainingWeight + 1;
  50. if (ncount[maxSymbolValue] == 1 && FUZZ_dataProducer_uint32Range(producer, 0, 1) == 1) {
  51. ncount[maxSymbolValue] = -1;
  52. }
  53. }
  54. /* Write the normalized count */
  55. {
  56. FUZZ_ASSERT(sizeof(data) >= FSE_NCountWriteBound(maxSymbolValue, tableLog));
  57. dataSize = FSE_writeNCount(data, sizeof(data), ncount, maxSymbolValue, tableLog);
  58. FUZZ_ZASSERT(dataSize);
  59. }
  60. /* Read & validate the normalized count */
  61. {
  62. short rtNcount[256];
  63. unsigned rtMaxSymbolValue = 255;
  64. unsigned rtTableLog;
  65. /* Copy into a buffer with a random amount of random data at the end */
  66. size_t const buffSize = (size_t)FUZZ_dataProducer_uint32Range(producer, dataSize, sizeof(data));
  67. BYTE* const buff = FUZZ_malloc(buffSize);
  68. size_t rtDataSize;
  69. memcpy(buff, data, dataSize);
  70. {
  71. size_t b;
  72. for (b = dataSize; b < buffSize; ++b) {
  73. buff[b] = (BYTE)FUZZ_dataProducer_uint32Range(producer, 0, 255);
  74. }
  75. }
  76. rtDataSize = FSE_readNCount(rtNcount, &rtMaxSymbolValue, &rtTableLog, buff, buffSize);
  77. FUZZ_ZASSERT(rtDataSize);
  78. FUZZ_ASSERT(rtDataSize == dataSize);
  79. FUZZ_ASSERT(rtMaxSymbolValue == maxSymbolValue);
  80. FUZZ_ASSERT(rtTableLog == tableLog);
  81. {
  82. unsigned s;
  83. for (s = 0; s <= maxSymbolValue; ++s) {
  84. FUZZ_ASSERT(ncount[s] == rtNcount[s]);
  85. }
  86. }
  87. free(buff);
  88. }
  89. FUZZ_dataProducer_free(producer);
  90. return 0;
  91. }