_ZN10FuzzHelperC2EPKhm:
   22|    130|{
   23|    130|}
_ZN10FuzzHelper8doChecksEv:
   27|    130|{
   28|    130|    Pl_Discard discard;
   29|    130|    Pl_TIFFPredictor p("decoder", &discard, Pl_TIFFPredictor::a_decode, 16, 1, 8);
   30|    130|    p.write(const_cast<unsigned char*>(data), size);
   31|    130|    p.finish();
   32|       |    // Exercise with strange values for some of the parameters.
   33|    130|    Pl_TIFFPredictor p2("decoder", &discard, Pl_TIFFPredictor::a_decode, 16, 2, 5);
   34|    130|    p2.write(const_cast<unsigned char*>(data), size);
   35|    130|    p2.finish();
   36|    130|}
_ZN10FuzzHelper3runEv:
   40|    130|{
   41|    130|    try {
   42|    130|        doChecks();
   43|    130|    } catch (std::runtime_error const& e) {
   44|      0|        std::cerr << "runtime_error: " << e.what() << std::endl;
   45|      0|    }
   46|    130|}
LLVMFuzzerTestOneInput:
   50|    130|{
   51|    130|    FuzzHelper f(data, size);
   52|    130|    f.run();
   53|    130|    return 0;
   54|    130|}

_ZN8PipelineD2Ev:
   53|    390|    virtual ~Pipeline() = default;

_ZN5QIntC7to_uintImEEjRKT_:
  207|   161k|    {
  208|   161k|        return IntConverter<T, unsigned int>::convert(i);
  209|   161k|    }
_ZN5QIntC12IntConverterImjLb0ELb0EE7convertERKm:
   68|   161k|        {
   69|       |            // From and To are both unsigned.
   70|   161k|            if (i > std::numeric_limits<To>::max()) {
  ------------------
  |  Branch (70:17): [True: 0, False: 161k]
  ------------------
   71|      0|                error(i);
   72|      0|            }
   73|   161k|            return static_cast<To>(i);
   74|   161k|        }

_ZN3QTC2TCEPKcS1_i:
   35|   362k|    {
   36|       |#ifndef QPDF_DISABLE_QTC
   37|       |        TC_real(scope, ccase, n);
   38|       |#endif // QPDF_DISABLE_QTC
   39|   362k|    }

_ZN9BitStreamC2EPKhm:
   12|   161k|{
   13|   161k|    reset();
   14|   161k|}
_ZN9BitStream5resetEv:
   18|   161k|{
   19|   161k|    p = start;
   20|   161k|    bit_offset = 7;
   21|   161k|    if (QIntC::to_uint(nbytes) > static_cast<unsigned int>(-1) / 8) {
  ------------------
  |  Branch (21:9): [True: 0, False: 161k]
  ------------------
   22|      0|        throw std::runtime_error("array too large for bitstream");
   23|      0|    }
   24|   161k|    bits_available = 8 * nbytes;
   25|   161k|}
_ZN9BitStream13getBitsSignedEm:
   35|  5.15M|{
   36|  5.15M|    unsigned long long bits = read_bits(this->p, this->bit_offset, this->bits_available, nbits);
   37|  5.15M|    long long result = 0;
   38|  5.15M|    if (static_cast<long long>(bits) > 1LL << (nbits - 1)) {
  ------------------
  |  Branch (38:9): [True: 1.10M, False: 4.05M]
  ------------------
   39|  1.10M|        result = static_cast<long long>(bits - (1ULL << nbits));
   40|  4.05M|    } else {
   41|  4.05M|        result = static_cast<long long>(bits);
   42|  4.05M|    }
   43|  5.15M|    return result;
   44|  5.15M|}

_ZN9BitWriterC2EP8Pipeline:
   11|   161k|{
   12|   161k|}
_ZN9BitWriter9writeBitsEym:
   16|  5.15M|{
   17|  5.15M|    write_bits(this->ch, this->bit_offset, val, bits, this->pl);
   18|  5.15M|}
_ZN9BitWriter15writeBitsSignedExm:
   22|  5.15M|{
   23|  5.15M|    unsigned long long uval = 0;
   24|  5.15M|    if (val < 0) {
  ------------------
  |  Branch (24:9): [True: 1.13M, False: 4.02M]
  ------------------
   25|  1.13M|        uval = (1ULL << bits) + static_cast<unsigned long long>(val);
   26|  4.02M|    } else {
   27|  4.02M|        uval = static_cast<unsigned long long>(val);
   28|  4.02M|    }
   29|  5.15M|    writeBits(uval, bits);
   30|  5.15M|}
_ZN9BitWriter5flushEv:
   40|   161k|{
   41|   161k|    if (bit_offset < 7) {
  ------------------
  |  Branch (41:9): [True: 0, False: 161k]
  ------------------
   42|      0|        size_t bits_to_write = bit_offset + 1;
   43|      0|        write_bits(this->ch, this->bit_offset, 0, bits_to_write, this->pl);
   44|      0|    }
   45|   161k|}

_ZN8PipelineC2EPKcPS_:
    9|    390|{
   10|    390|}
_ZN8Pipeline7getNextEb:
   14|    260|{
   15|    260|    if ((this->next == nullptr) && (!allow_null)) {
  ------------------
  |  Branch (15:9): [True: 0, False: 260]
  |  Branch (15:36): [True: 0, False: 0]
  ------------------
   16|      0|        throw std::logic_error(
   17|      0|            this->identifier + ": Pipeline::getNext() called on pipeline with no next");
   18|      0|    }
   19|    260|    return this->next;
   20|    260|}

_ZN10Pl_DiscardC2Ev:
    7|    130|{
    8|    130|}
_ZN10Pl_DiscardD2Ev:
   11|    130|{
   12|       |    // Must be explicit and not inline -- see QPDF_DLL_CLASS in README-maintainer
   13|    130|}
_ZN10Pl_Discard5writeEPKhm:
   17|  3.42M|{
   18|  3.42M|}
_ZN10Pl_Discard6finishEv:
   22|    260|{
   23|    260|}

_ZN16Pl_TIFFPredictorC2EPKcP8PipelineNS_8action_eEjjj:
   28|    260|{
   29|    260|    if (samples_per_pixel < 1) {
  ------------------
  |  Branch (29:9): [True: 0, False: 260]
  ------------------
   30|      0|        throw std::runtime_error("TIFFPredictor created with invalid samples_per_pixel");
   31|      0|    }
   32|    260|    if ((bits_per_sample < 1) || (bits_per_sample > (8 * (sizeof(unsigned long long))))) {
  ------------------
  |  Branch (32:9): [True: 0, False: 260]
  |  Branch (32:34): [True: 0, False: 260]
  ------------------
   33|      0|        throw std::runtime_error("TIFFPredictor created with invalid bits_per_sample");
   34|      0|    }
   35|    260|    unsigned long long bpr = ((columns * bits_per_sample * samples_per_pixel) + 7) / 8;
   36|    260|    if ((bpr == 0) || (bpr > (UINT_MAX - 1))) {
  ------------------
  |  Branch (36:9): [True: 0, False: 260]
  |  Branch (36:23): [True: 0, False: 260]
  ------------------
   37|      0|        throw std::runtime_error("TIFFPredictor created with invalid columns value");
   38|      0|    }
   39|    260|    if (memory_limit > 0 && bpr > (memory_limit / 2U)) {
  ------------------
  |  Branch (39:9): [True: 0, False: 260]
  |  Branch (39:29): [True: 0, False: 0]
  ------------------
   40|      0|        throw std::runtime_error("TIFFPredictor memory limit exceeded");
   41|      0|    }
   42|    260|    this->bytes_per_row = bpr & UINT_MAX;
   43|    260|}
_ZN16Pl_TIFFPredictor5writeEPKhm:
   53|    260|{
   54|    260|    auto end = data + len;
   55|    260|    auto row_end = data + (bytes_per_row - cur_row.size());
   56|   362k|    while (row_end <= end) {
  ------------------
  |  Branch (56:12): [True: 362k, False: 260]
  ------------------
   57|       |        // finish off current row
   58|   362k|        cur_row.insert(cur_row.end(), data, row_end);
   59|   362k|        data = row_end;
   60|   362k|        row_end += bytes_per_row;
   61|       |
   62|   362k|        processRow();
   63|       |
   64|       |        // Prepare for next row
   65|   362k|        cur_row.clear();
   66|   362k|    }
   67|       |
   68|    260|    cur_row.insert(cur_row.end(), data, end);
   69|    260|}
_ZN16Pl_TIFFPredictor10processRowEv:
   73|   362k|{
   74|   362k|    QTC::TC("libtests", "Pl_TIFFPredictor processRow", (action == a_decode ? 0 : 1));
  ------------------
  |  Branch (74:57): [True: 362k, False: 0]
  ------------------
   75|   362k|    previous.assign(samples_per_pixel, 0);
   76|   362k|    if (bits_per_sample != 8) {
  ------------------
  |  Branch (76:9): [True: 161k, False: 201k]
  ------------------
   77|   161k|        BitWriter bw(p_next);
   78|   161k|        BitStream in(cur_row.data(), cur_row.size());
   79|  2.73M|        for (unsigned int col = 0; col < this->columns; ++col) {
  ------------------
  |  Branch (79:36): [True: 2.57M, False: 161k]
  ------------------
   80|  5.15M|            for (auto& prev: previous) {
  ------------------
  |  Branch (80:28): [True: 5.15M, False: 2.57M]
  ------------------
   81|  5.15M|                long long sample = in.getBitsSigned(this->bits_per_sample);
   82|  5.15M|                long long new_sample = sample;
   83|  5.15M|                if (action == a_encode) {
  ------------------
  |  Branch (83:21): [True: 0, False: 5.15M]
  ------------------
   84|      0|                    new_sample -= prev;
   85|      0|                    prev = sample;
   86|  5.15M|                } else {
   87|  5.15M|                    new_sample += prev;
   88|  5.15M|                    prev = new_sample;
   89|  5.15M|                }
   90|  5.15M|                bw.writeBitsSigned(new_sample, this->bits_per_sample);
   91|  5.15M|            }
   92|  2.57M|        }
   93|   161k|        bw.flush();
   94|   201k|    } else {
   95|   201k|        out.clear();
   96|   201k|        auto next = cur_row.begin();
   97|   201k|        auto cr_end = cur_row.end();
   98|   201k|        auto pr_end = previous.end();
   99|       |
  100|  3.42M|        while (next != cr_end) {
  ------------------
  |  Branch (100:16): [True: 3.22M, False: 201k]
  ------------------
  101|  6.44M|            for (auto prev = previous.begin(); prev != pr_end && next != cr_end; ++prev, ++next) {
  ------------------
  |  Branch (101:48): [True: 3.22M, False: 3.22M]
  |  Branch (101:66): [True: 3.22M, False: 0]
  ------------------
  102|  3.22M|                long long sample = *next;
  103|  3.22M|                long long new_sample = sample;
  104|  3.22M|                if (action == a_encode) {
  ------------------
  |  Branch (104:21): [True: 0, False: 3.22M]
  ------------------
  105|      0|                    new_sample -= *prev;
  106|      0|                    *prev = sample;
  107|  3.22M|                } else {
  108|  3.22M|                    new_sample += *prev;
  109|  3.22M|                    *prev = new_sample;
  110|  3.22M|                }
  111|  3.22M|                out.push_back(static_cast<unsigned char>(255U & new_sample));
  112|  3.22M|            }
  113|  3.22M|        }
  114|   201k|        p_next->write(out.data(), out.size());
  115|   201k|    }
  116|   362k|}
_ZN16Pl_TIFFPredictor6finishEv:
  120|    260|{
  121|    260|    if (!cur_row.empty()) {
  ------------------
  |  Branch (121:9): [True: 237, False: 23]
  ------------------
  122|       |        // write partial row
  123|    237|        cur_row.insert(cur_row.end(), bytes_per_row - cur_row.size(), 0);
  124|    237|        processRow();
  125|    237|    }
  126|    260|    cur_row.clear();
  127|    260|    p_next->finish();
  128|    260|}

_ZN16Pl_TIFFPredictorD2Ev:
   23|    260|    ~Pl_TIFFPredictor() override = default;

BitStream.cc:_ZL9read_bitsRPKhRmS2_m:
   21|  5.15M|{
   22|       |    // View p as a stream of bits:
   23|       |
   24|       |    // 76543210 76543210 ....
   25|       |
   26|       |    // bit_offset is the bit number within the first byte that marks
   27|       |    // the first bit that we would read.
   28|       |
   29|  5.15M|    if (bits_wanted > bits_available) {
  ------------------
  |  Branch (29:9): [True: 0, False: 5.15M]
  ------------------
   30|      0|        throw std::runtime_error(
   31|      0|            "overflow reading bit stream: wanted = " + std::to_string(bits_wanted) +
   32|      0|            "; available = " + std::to_string(bits_available));
   33|      0|    }
   34|  5.15M|    if (bits_wanted > 32) {
  ------------------
  |  Branch (34:9): [True: 0, False: 5.15M]
  ------------------
   35|      0|        throw std::out_of_range("read_bits: too many bits requested");
   36|      0|    }
   37|       |
   38|  5.15M|    unsigned long result = 0;
   39|       |# ifdef BITS_TESTING
   40|       |    if (bits_wanted == 0) {
   41|       |        QTC::TC("libtests", "bits zero bits wanted");
   42|       |    }
   43|       |# endif
   44|  12.8M|    while (bits_wanted > 0) {
  ------------------
  |  Branch (44:12): [True: 7.73M, False: 5.15M]
  ------------------
   45|       |        // Grab bits from the first byte clearing anything before
   46|       |        // bit_offset.
   47|  7.73M|        unsigned char byte = static_cast<unsigned char>(*p & ((1U << (bit_offset + 1U)) - 1U));
   48|       |
   49|       |        // There are bit_offset + 1 bits available in the first byte.
   50|  7.73M|        size_t to_copy = std::min(bits_wanted, bit_offset + 1);
   51|  7.73M|        size_t leftover = (bit_offset + 1) - to_copy;
   52|       |
   53|       |# ifdef BITS_TESTING
   54|       |        QTC::TC("libtests", "bits bit_offset", ((bit_offset == 0) ? 0 : (bit_offset == 7) ? 1 : 2));
   55|       |        QTC::TC("libtests", "bits leftover", (leftover > 0) ? 1 : 0);
   56|       |# endif
   57|       |
   58|       |        // Right shift so that all the bits we want are right justified.
   59|  7.73M|        byte = static_cast<unsigned char>(byte >> leftover);
   60|       |
   61|       |        // Copy the bits into result
   62|  7.73M|        result <<= to_copy;
   63|  7.73M|        result |= byte;
   64|       |
   65|       |        // Update pointers
   66|  7.73M|        if (leftover) {
  ------------------
  |  Branch (66:13): [True: 4.51M, False: 3.22M]
  ------------------
   67|  4.51M|            bit_offset = leftover - 1;
   68|  4.51M|        } else {
   69|  3.22M|            bit_offset = 7;
   70|  3.22M|            ++p;
   71|  3.22M|        }
   72|  7.73M|        bits_wanted -= to_copy;
   73|  7.73M|        bits_available -= to_copy;
   74|       |
   75|       |# ifdef BITS_TESTING
   76|       |        QTC::TC("libtests", "bits iterations", ((bits_wanted > 8) ? 0 : (bits_wanted > 0) ? 1 : 2));
   77|       |# endif
   78|  7.73M|    }
   79|       |
   80|  5.15M|    return result;
   81|  5.15M|}
BitWriter.cc:_ZL10write_bitsRhRmymP8Pipeline:
   88|  5.15M|{
   89|  5.15M|    if (bits > 32) {
  ------------------
  |  Branch (89:9): [True: 0, False: 5.15M]
  ------------------
   90|      0|        throw std::out_of_range("write_bits: too many bits requested");
   91|      0|    }
   92|       |
   93|       |    // bit_offset + 1 is the number of bits left in ch
   94|       |# ifdef BITS_TESTING
   95|       |    if (bits == 0) {
   96|       |        QTC::TC("libtests", "bits write zero bits");
   97|       |    }
   98|       |# endif
   99|  12.8M|    while (bits > 0) {
  ------------------
  |  Branch (99:12): [True: 7.73M, False: 5.15M]
  ------------------
  100|  7.73M|        size_t bits_to_write = std::min(bits, bit_offset + 1);
  101|  7.73M|        unsigned char newval = static_cast<unsigned char>(
  102|  7.73M|            (val >> (bits - bits_to_write)) & ((1U << bits_to_write) - 1));
  103|  7.73M|        size_t bits_left_in_ch = bit_offset + 1 - bits_to_write;
  104|  7.73M|        newval = static_cast<unsigned char>(newval << bits_left_in_ch);
  105|  7.73M|        ch |= newval;
  106|  7.73M|        if (bits_left_in_ch == 0) {
  ------------------
  |  Branch (106:13): [True: 3.22M, False: 4.51M]
  ------------------
  107|       |# ifdef BITS_TESTING
  108|       |            QTC::TC("libtests", "bits write pipeline");
  109|       |# endif
  110|  3.22M|            pipeline->write(&ch, 1);
  111|  3.22M|            bit_offset = 7;
  112|  3.22M|            ch = 0;
  113|  4.51M|        } else {
  114|       |# ifdef BITS_TESTING
  115|       |            QTC::TC("libtests", "bits write leftover");
  116|       |# endif
  117|  4.51M|            bit_offset -= bits_to_write;
  118|  4.51M|        }
  119|  7.73M|        bits -= bits_to_write;
  120|       |# ifdef BITS_TESTING
  121|       |        QTC::TC("libtests", "bits write iterations", ((bits > 8) ? 0 : (bits > 0) ? 1 : 2));
  122|       |# endif
  123|  7.73M|    }
  124|  5.15M|}

