source: rtems/cpukit/libfs/src/jffs2/src/compr_rtime.c @ 2ea03be

Last change on this file since 2ea03be was 2ea03be, checked in by Sebastian Huber <sebastian.huber@…>, on 01/12/23 at 13:38:36

jffs2: Fix return code of rtime compress

The RTEMS and Linux JFFS2 compression support have a slightly different
interface. This fixes a bug introduced by:

commit 17c3d536ca8ee17d36ea251eade884e07ff1ee75
Author: Yang Yang <yang.yang29@…>
Date: Thu Jan 28 02:55:35 2021 -0800

jffs2: check the validity of dstlen in jffs2_zlib_compress()

KASAN reports a BUG when download file in jffs2 filesystem.It is
because when dstlen == 1, cpage_out will write array out of bounds.
Actually, data will not be compressed in jffs2_zlib_compress() if
data's length less than 4.

  • Property mode set to 100644
File size: 2.6 KB
Line 
1#include "rtems-jffs2-config.h"
2
3/*
4 * JFFS2 -- Journalling Flash File System, Version 2.
5 *
6 * Copyright © 2001-2007 Red Hat, Inc.
7 * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
8 *
9 * Created by Arjan van de Ven <arjanv@redhat.com>
10 *
11 * For licensing information, see the file 'LICENCE' in this directory.
12 *
13 *
14 *
15 * Very simple lz77-ish encoder.
16 *
17 * Theory of operation: Both encoder and decoder have a list of "last
18 * occurrences" for every possible source-value; after sending the
19 * first source-byte, the second byte indicated the "run" length of
20 * matches
21 *
22 * The algorithm is intended to only send "whole bytes", no bit-messing.
23 *
24 */
25
26#include <linux/kernel.h>
27#include <linux/types.h>
28#include <linux/errno.h>
29#include <linux/string.h>
30#include <linux/jffs2.h>
31#include "compr.h"
32
33uint16_t rtems_jffs2_compressor_rtime_compress(
34        rtems_jffs2_compressor_control *self,
35        unsigned char *data_in,
36        unsigned char *cpage_out,
37        uint32_t *sourcelen,
38        uint32_t *dstlen
39)
40{
41        unsigned short positions[256];
42        int outpos = 0;
43        int pos=0;
44
45        (void) self;
46
47        if (*dstlen <= 3)
48                return JFFS2_COMPR_NONE;
49
50        memset(positions,0,sizeof(positions));
51
52        while (pos < (*sourcelen) && outpos <= (*dstlen)-2) {
53                int backpos, runlen=0;
54                unsigned char value;
55
56                value = data_in[pos];
57
58                cpage_out[outpos++] = data_in[pos++];
59
60                backpos = positions[value];
61                positions[value]=pos;
62
63                while ((backpos < pos) && (pos < (*sourcelen)) &&
64                       (data_in[pos]==data_in[backpos++]) && (runlen<255)) {
65                        pos++;
66                        runlen++;
67                }
68                cpage_out[outpos++] = runlen;
69        }
70
71        if (outpos >= pos) {
72                /* We failed */
73                return JFFS2_COMPR_NONE;
74        }
75
76        /* Tell the caller how much we managed to compress, and how much space it took */
77        *sourcelen = pos;
78        *dstlen = outpos;
79        return JFFS2_COMPR_RTIME;
80}
81
82
83int rtems_jffs2_compressor_rtime_decompress(
84        rtems_jffs2_compressor_control *self,
85        uint16_t comprtype,
86        unsigned char *data_in,
87        unsigned char *cpage_out,
88        uint32_t srclen,
89        uint32_t destlen
90)
91{
92        unsigned short positions[256];
93        int outpos = 0;
94        int pos=0;
95
96        (void) self;
97
98        if (comprtype != JFFS2_COMPR_RTIME) {
99                return -EIO;
100        }
101
102        memset(positions,0,sizeof(positions));
103
104        while (outpos<destlen) {
105                unsigned char value;
106                int backoffs;
107                int repeat;
108
109                value = data_in[pos++];
110                cpage_out[outpos++] = value; /* first the verbatim copied byte */
111                repeat = data_in[pos++];
112                backoffs = positions[value];
113
114                positions[value]=outpos;
115                if (repeat) {
116                        if (backoffs + repeat >= outpos) {
117                                while(repeat) {
118                                        cpage_out[outpos++] = cpage_out[backoffs++];
119                                        repeat--;
120                                }
121                        } else {
122                                memcpy(&cpage_out[outpos],&cpage_out[backoffs],repeat);
123                                outpos+=repeat;
124                        }
125                }
126        }
127        return 0;
128}
Note: See TracBrowser for help on using the repository browser.