Skip to content

Potential size_t underflow leads to Segmentation Fault #2

Description

@6en6ar

Inside zstdD.c on line 623. there is a potential size_t underflow condition

            p_lit += ll;
--> [1]  n_lit -= ll;
            of = parse_offset(p_ctx->prev_of, of, ll);
            for (; ml>0; ml--) {
                **pp_dst = *(*pp_dst - of);
                (*pp_dst) ++;
            }

            if (++i >= n_seq) break;

            backward_stream_load(&bst);
            ll_state = p_ctx->table_ll.state_base[ll_state] + backward_stream_readmove(&bst, p_ctx->table_ll.n_bits[ll_state]);
            ml_state = p_ctx->table_ml.state_base[ml_state] + backward_stream_readmove(&bst, p_ctx->table_ml.n_bits[ml_state]);
            of_state = p_ctx->table_of.state_base[of_state] + backward_stream_readmove(&bst, p_ctx->table_of.n_bits[of_state]);
        }

        backward_stream_check_ended(&bst);
    }

->[2] memcpy(*pp_dst, p_lit, n_lit);
    (*pp_dst) += n_lit;

If size_t supplied variable "n_lit" that is sent to the function decode_sequences_by_fse_and_execute is set to 0
then that value will be deducted from "ll" causing a size_t underflow. In the following payload the "ll" variable is set to 0xa
causing the value to be 0xfffffffffffffff6 (18446744073709551606) which is decremented even more in the for loop
and later supplied as a size parameter to memcpy [2] causing a very large copy to destination causing memcpy to send SEGFAULT.

The payload ->

00000000: 28b5 2ffd 2405 4500 0000 0200 1500 1001  (./.$.E.........
00000010: ba64                                     .d

[crash_zstd.txt](https://github.com/user-attachments/files/22731121/crash_zstd.txt)

Reproduce:
./tinyZZZ -d --zstd crash_zstd.zstd test.txt

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions