LCOV - code coverage report
Current view: top level - libavutil - lzo.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 77 104 74.0 %
Date: 2017-12-15 02:19:58 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * LZO 1x decompression
       3             :  * Copyright (c) 2006 Reimar Doeffinger
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include <string.h>
      23             : 
      24             : #include "avutil.h"
      25             : #include "avassert.h"
      26             : #include "common.h"
      27             : #include "intreadwrite.h"
      28             : #include "lzo.h"
      29             : 
      30             : /// Define if we may write up to 12 bytes beyond the output buffer.
      31             : #define OUTBUF_PADDED 1
      32             : /// Define if we may read up to 8 bytes beyond the input buffer.
      33             : #define INBUF_PADDED 1
      34             : 
      35             : typedef struct LZOContext {
      36             :     const uint8_t *in, *in_end;
      37             :     uint8_t *out_start, *out, *out_end;
      38             :     int error;
      39             : } LZOContext;
      40             : 
      41             : /**
      42             :  * @brief Reads one byte from the input buffer, avoiding an overrun.
      43             :  * @return byte read
      44             :  */
      45      307119 : static inline int get_byte(LZOContext *c)
      46             : {
      47      307119 :     if (c->in < c->in_end)
      48      307119 :         return *c->in++;
      49           0 :     c->error |= AV_LZO_INPUT_DEPLETED;
      50           0 :     return 1;
      51             : }
      52             : 
      53             : #ifdef INBUF_PADDED
      54             : #define GETB(c) (*(c).in++)
      55             : #else
      56             : #define GETB(c) get_byte(&(c))
      57             : #endif
      58             : 
      59             : /**
      60             :  * @brief Decodes a length value in the coding used by lzo.
      61             :  * @param x previous byte value
      62             :  * @param mask bits used from x
      63             :  * @return decoded length value
      64             :  */
      65       64581 : static inline int get_len(LZOContext *c, int x, int mask)
      66             : {
      67       64581 :     int cnt = x & mask;
      68       64581 :     if (!cnt) {
      69      326494 :         while (!(x = get_byte(c))) {
      70      287744 :             if (cnt >= INT_MAX - 1000) {
      71           0 :                 c->error |= AV_LZO_ERROR;
      72           0 :                 break;
      73             :             }
      74      287744 :             cnt += 255;
      75             :         }
      76       19375 :         cnt += mask + x;
      77             :     }
      78       64581 :     return cnt;
      79             : }
      80             : 
      81             : /**
      82             :  * @brief Copies bytes from input to output buffer with checking.
      83             :  * @param cnt number of bytes to copy, must be >= 0
      84             :  */
      85      133524 : static inline void copy(LZOContext *c, int cnt)
      86             : {
      87      133524 :     register const uint8_t *src = c->in;
      88      133524 :     register uint8_t *dst       = c->out;
      89      133524 :     av_assert0(cnt >= 0);
      90      133524 :     if (cnt > c->in_end - src) {
      91           0 :         cnt       = FFMAX(c->in_end - src, 0);
      92           0 :         c->error |= AV_LZO_INPUT_DEPLETED;
      93             :     }
      94      133524 :     if (cnt > c->out_end - dst) {
      95           0 :         cnt       = FFMAX(c->out_end - dst, 0);
      96           0 :         c->error |= AV_LZO_OUTPUT_FULL;
      97             :     }
      98             : #if defined(INBUF_PADDED) && defined(OUTBUF_PADDED)
      99      133524 :     AV_COPY32U(dst, src);
     100      133524 :     src += 4;
     101      133524 :     dst += 4;
     102      133524 :     cnt -= 4;
     103      133524 :     if (cnt > 0)
     104             : #endif
     105       25118 :     memcpy(dst, src, cnt);
     106      133524 :     c->in  = src + cnt;
     107      133524 :     c->out = dst + cnt;
     108      133524 : }
     109             : 
     110             : /**
     111             :  * @brief Copies previously decoded bytes to current position.
     112             :  * @param back how many bytes back we start, must be > 0
     113             :  * @param cnt number of bytes to copy, must be > 0
     114             :  *
     115             :  * cnt > back is valid, this will copy the bytes we just copied,
     116             :  * thus creating a repeating pattern with a period length of back.
     117             :  */
     118      105210 : static inline void copy_backptr(LZOContext *c, int back, int cnt)
     119             : {
     120      105210 :     register uint8_t *dst       = c->out;
     121      105210 :     av_assert0(cnt > 0);
     122      105210 :     if (dst - c->out_start < back) {
     123           0 :         c->error |= AV_LZO_INVALID_BACKPTR;
     124           0 :         return;
     125             :     }
     126      105210 :     if (cnt > c->out_end - dst) {
     127           0 :         cnt       = FFMAX(c->out_end - dst, 0);
     128           0 :         c->error |= AV_LZO_OUTPUT_FULL;
     129             :     }
     130      105210 :     av_memcpy_backptr(dst, back, cnt);
     131      105210 :     c->out = dst + cnt;
     132             : }
     133             : 
     134         266 : int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen)
     135             : {
     136         266 :     int state = 0;
     137             :     int x;
     138             :     LZOContext c;
     139         266 :     if (*outlen <= 0 || *inlen <= 0) {
     140           0 :         int res = 0;
     141           0 :         if (*outlen <= 0)
     142           0 :             res |= AV_LZO_OUTPUT_FULL;
     143           0 :         if (*inlen <= 0)
     144           0 :             res |= AV_LZO_INPUT_DEPLETED;
     145           0 :         return res;
     146             :     }
     147         266 :     c.in      = in;
     148         266 :     c.in_end  = (const uint8_t *)in + *inlen;
     149         266 :     c.out     = c.out_start = out;
     150         266 :     c.out_end = (uint8_t *)out + *outlen;
     151         266 :     c.error   = 0;
     152         266 :     x         = GETB(c);
     153         266 :     if (x > 17) {
     154           0 :         copy(&c, x - 17);
     155           0 :         x = GETB(c);
     156           0 :         if (x < 16)
     157           0 :             c.error |= AV_LZO_ERROR;
     158             :     }
     159         266 :     if (c.in > c.in_end)
     160           0 :         c.error |= AV_LZO_INPUT_DEPLETED;
     161      134056 :     while (!c.error) {
     162             :         int cnt, back;
     163      133790 :         if (x > 15) {
     164      105476 :             if (x > 63) {
     165       69209 :                 cnt  = (x >> 5) - 1;
     166       69209 :                 back = (GETB(c) << 3) + ((x >> 2) & 7) + 1;
     167       36267 :             } else if (x > 31) {
     168       34878 :                 cnt  = get_len(&c, x, 31);
     169       34878 :                 x    = GETB(c);
     170       34878 :                 back = (GETB(c) << 6) + (x >> 2) + 1;
     171             :             } else {
     172        1389 :                 cnt   = get_len(&c, x, 7);
     173        1389 :                 back  = (1 << 14) + ((x & 8) << 11);
     174        1389 :                 x     = GETB(c);
     175        1389 :                 back += (GETB(c) << 6) + (x >> 2);
     176        1389 :                 if (back == (1 << 14)) {
     177         266 :                     if (cnt != 1)
     178           1 :                         c.error |= AV_LZO_ERROR;
     179         266 :                     break;
     180             :                 }
     181             :             }
     182       28314 :         } else if (!state) {
     183       28314 :             cnt = get_len(&c, x, 15);
     184       28314 :             copy(&c, cnt + 3);
     185       28314 :             x = GETB(c);
     186       28314 :             if (x > 15)
     187       28314 :                 continue;
     188           0 :             cnt  = 1;
     189           0 :             back = (1 << 11) + (GETB(c) << 2) + (x >> 2) + 1;
     190             :         } else {
     191           0 :             cnt  = 0;
     192           0 :             back = (GETB(c) << 2) + (x >> 2) + 1;
     193             :         }
     194      105210 :         copy_backptr(&c, back, cnt + 2);
     195      105210 :         state =
     196      105210 :         cnt   = x & 3;
     197      105210 :         copy(&c, cnt);
     198      105210 :         x = GETB(c);
     199             :     }
     200         266 :     *inlen = c.in_end - c.in;
     201         266 :     if (c.in > c.in_end)
     202           1 :         *inlen = 0;
     203         266 :     *outlen = c.out_end - c.out;
     204         266 :     return c.error;
     205             : }

Generated by: LCOV version 1.13