Coverage Report

Created: 2024-09-06 07:53

/src/ffmpeg/libavcodec/mlz.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016 Umair Khan <omerjerk@gmail.com>
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#include "libavutil/mem.h"
22
#include "mlz.h"
23
24
av_cold int ff_mlz_init_dict(void *context, MLZ *mlz)
25
883
{
26
883
    mlz->dict = av_mallocz(TABLE_SIZE * sizeof(*mlz->dict));
27
883
    if (!mlz->dict)
28
0
        return AVERROR(ENOMEM);
29
30
883
    mlz->flush_code            = FLUSH_CODE;
31
883
    mlz->current_dic_index_max = DIC_INDEX_INIT;
32
883
    mlz->dic_code_bit          = CODE_BIT_INIT;
33
883
    mlz->bump_code             = (DIC_INDEX_INIT - 1);
34
883
    mlz->next_code             = FIRST_CODE;
35
883
    mlz->freeze_flag           = 0;
36
883
    mlz->context               = context;
37
38
883
    return 0;
39
883
}
40
41
227k
av_cold void ff_mlz_flush_dict(MLZ *mlz) {
42
227k
    MLZDict *dict = mlz->dict;
43
227k
    int i;
44
7.97G
    for ( i = 0; i < TABLE_SIZE; i++ ) {
45
7.97G
        dict[i].string_code = CODE_UNSET;
46
7.97G
        dict[i].parent_code = CODE_UNSET;
47
7.97G
        dict[i].match_len = 0;
48
7.97G
    }
49
227k
    mlz->current_dic_index_max = DIC_INDEX_INIT;
50
227k
    mlz->dic_code_bit          = CODE_BIT_INIT;  // DicCodeBitInit;
51
227k
    mlz->bump_code             = mlz->current_dic_index_max - 1;
52
227k
    mlz->next_code             = FIRST_CODE;
53
227k
    mlz->freeze_flag           = 0;
54
227k
}
55
56
86.0M
static void set_new_entry_dict(MLZDict* dict, int string_code, int parent_code, int char_code) {
57
86.0M
    dict[string_code].parent_code = parent_code;
58
86.0M
    dict[string_code].string_code = string_code;
59
86.0M
    dict[string_code].char_code   = char_code;
60
86.0M
    if (parent_code < FIRST_CODE) {
61
85.1M
        dict[string_code].match_len = 2;
62
85.1M
    } else {
63
917k
        dict[string_code].match_len = (dict[parent_code].match_len) + 1;
64
917k
    }
65
86.0M
}
66
67
96.7M
static int decode_string(MLZ* mlz, unsigned char *buff, int string_code, int *first_char_code, unsigned long bufsize) {
68
96.7M
    MLZDict* dict = mlz->dict;
69
96.7M
    unsigned long count, offset;
70
96.7M
    int current_code, parent_code, tmp_code;
71
72
96.7M
    count            = 0;
73
96.7M
    current_code     = string_code;
74
96.7M
    *first_char_code = CODE_UNSET;
75
76
147M
    while (count < bufsize) {
77
147M
        switch (current_code) {
78
627k
        case CODE_UNSET:
79
627k
            return count;
80
0
            break;
81
146M
        default:
82
146M
            if (current_code < FIRST_CODE) {
83
95.4M
                *first_char_code = current_code;
84
95.4M
                buff[0] = current_code;
85
95.4M
                count++;
86
95.4M
                return count;
87
95.4M
            } else {
88
51.1M
                offset  = dict[current_code].match_len - 1;
89
51.1M
                tmp_code = dict[current_code].char_code;
90
51.1M
                if (offset >= bufsize) {
91
559k
                    av_log(mlz->context, AV_LOG_ERROR, "MLZ offset error.\n");
92
559k
                    return count;
93
559k
                }
94
50.5M
                buff[offset] = tmp_code;
95
50.5M
                count++;
96
50.5M
            }
97
50.5M
            current_code = dict[current_code].parent_code;
98
50.5M
            if ((current_code < 0) || (current_code > (DIC_INDEX_MAX - 1))) {
99
12.9k
                av_log(mlz->context, AV_LOG_ERROR, "MLZ dic index error.\n");
100
12.9k
                return count;
101
12.9k
            }
102
50.5M
            if (current_code > FIRST_CODE) {
103
50.4M
                parent_code = dict[current_code].parent_code;
104
50.4M
                offset = (dict[current_code].match_len) - 1;
105
50.4M
                if (parent_code < 0 || parent_code > DIC_INDEX_MAX-1) {
106
126k
                    av_log(mlz->context, AV_LOG_ERROR, "MLZ dic index error.\n");
107
126k
                    return count;
108
126k
                }
109
50.2M
                if (( offset > (DIC_INDEX_MAX - 1))) {
110
0
                    av_log(mlz->context, AV_LOG_ERROR, "MLZ dic offset error.\n");
111
0
                    return count;
112
0
                }
113
50.2M
            }
114
50.4M
            break;
115
147M
        }
116
147M
    }
117
53.0k
    return count;
118
96.7M
}
119
120
97.3M
static int input_code(GetBitContext* gb, int len) {
121
97.3M
    int tmp_code = 0;
122
97.3M
    int i;
123
1.06G
    for (i = 0; i < len; ++i) {
124
963M
        tmp_code |= get_bits1(gb) << i;
125
963M
    }
126
97.3M
    return tmp_code;
127
97.3M
}
128
129
149k
int ff_mlz_decompression(MLZ* mlz, GetBitContext* gb, int size, unsigned char *buff) {
130
149k
    MLZDict *dict = mlz->dict;
131
149k
    unsigned long output_chars;
132
149k
    int string_code, last_string_code, char_code;
133
134
149k
    string_code = 0;
135
149k
    char_code   = -1;
136
149k
    last_string_code = -1;
137
149k
    output_chars = 0;
138
139
97.5M
    while (output_chars < size) {
140
97.3M
        string_code = input_code(gb, mlz->dic_code_bit);
141
97.3M
        switch (string_code) {
142
5.42k
            case FLUSH_CODE:
143
185k
            case MAX_CODE:
144
185k
                ff_mlz_flush_dict(mlz);
145
185k
                char_code = -1;
146
185k
                last_string_code = -1;
147
185k
                break;
148
2.85k
            case FREEZE_CODE:
149
2.85k
                mlz->freeze_flag = 1;
150
2.85k
                break;
151
97.1M
            default:
152
97.1M
                if (string_code > mlz->current_dic_index_max) {
153
0
                    av_log(mlz->context, AV_LOG_ERROR, "String code %d exceeds maximum value of %d.\n", string_code, mlz->current_dic_index_max);
154
0
                    return output_chars;
155
0
                }
156
97.1M
                if (string_code == (int) mlz->bump_code) {
157
1.08M
                    ++mlz->dic_code_bit;
158
1.08M
                    mlz->current_dic_index_max *= 2;
159
1.08M
                    mlz->bump_code = mlz->current_dic_index_max - 1;
160
96.1M
                } else {
161
96.1M
                    if (string_code >= mlz->next_code) {
162
680k
                        int ret = decode_string(mlz, &buff[output_chars], last_string_code, &char_code, size - output_chars);
163
680k
                        if (ret < 0 || ret > size - output_chars) {
164
0
                            av_log(mlz->context, AV_LOG_ERROR, "output chars overflow\n");
165
0
                            return output_chars;
166
0
                        }
167
680k
                        output_chars += ret;
168
680k
                        ret = decode_string(mlz, &buff[output_chars], char_code, &char_code, size - output_chars);
169
680k
                        if (ret < 0 || ret > size - output_chars) {
170
0
                            av_log(mlz->context, AV_LOG_ERROR, "output chars overflow\n");
171
0
                            return output_chars;
172
0
                        }
173
680k
                        output_chars += ret;
174
680k
                        set_new_entry_dict(dict, mlz->next_code, last_string_code, char_code);
175
680k
                        if (mlz->next_code >= TABLE_SIZE - 1) {
176
0
                            av_log(mlz->context, AV_LOG_ERROR, "Too many MLZ codes\n");
177
0
                            return output_chars;
178
0
                        }
179
680k
                        mlz->next_code++;
180
95.4M
                    } else {
181
95.4M
                        int ret = decode_string(mlz, &buff[output_chars], string_code, &char_code, size - output_chars);
182
95.4M
                        if (ret < 0 || ret > size - output_chars) {
183
0
                            av_log(mlz->context, AV_LOG_ERROR, "output chars overflow\n");
184
0
                            return output_chars;
185
0
                        }
186
95.4M
                        output_chars += ret;
187
95.4M
                        if (output_chars <= size && !mlz->freeze_flag) {
188
85.4M
                            if (last_string_code != -1) {
189
85.3M
                                set_new_entry_dict(dict, mlz->next_code, last_string_code, char_code);
190
85.3M
                                if (mlz->next_code >= TABLE_SIZE - 1) {
191
2.84k
                                    av_log(mlz->context, AV_LOG_ERROR, "Too many MLZ codes\n");
192
2.84k
                                    return output_chars;
193
2.84k
                                }
194
85.3M
                                mlz->next_code++;
195
85.3M
                            }
196
85.4M
                        } else {
197
9.94M
                            break;
198
9.94M
                        }
199
95.4M
                    }
200
86.1M
                    last_string_code = string_code;
201
86.1M
                }
202
87.2M
                break;
203
97.3M
        }
204
97.3M
    }
205
147k
    return output_chars;
206
149k
}