LCOV - code coverage report
Current view: top level - libavcodec - snappy.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 69 88 78.4 %
Date: 2017-12-17 11:58:42 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /*
       2             :  * Snappy decompression algorithm
       3             :  * Copyright (c) 2015 Luca Barbato
       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 "libavutil/mem.h"
      23             : 
      24             : #include "bytestream.h"
      25             : #include "snappy.h"
      26             : 
      27             : enum {
      28             :     SNAPPY_LITERAL,
      29             :     SNAPPY_COPY_1,
      30             :     SNAPPY_COPY_2,
      31             :     SNAPPY_COPY_4,
      32             : };
      33             : 
      34         100 : static int64_t bytestream2_get_levarint(GetByteContext *gb)
      35             : {
      36         100 :     uint64_t val = 0;
      37         100 :     int shift = 0;
      38             :     int tmp;
      39             : 
      40             :     do {
      41         206 :         tmp = bytestream2_get_byte(gb);
      42         206 :         val |= (tmp & 127) << shift;
      43         206 :         shift += 7;
      44         206 :     } while (tmp & 128);
      45             : 
      46         100 :     return val;
      47             : }
      48             : 
      49       26644 : static int snappy_literal(GetByteContext *gb, uint8_t *p, int size, int val)
      50             : {
      51       26644 :     unsigned int len = 1;
      52             : 
      53       26644 :     switch (val) {
      54           0 :     case 63:
      55           0 :         len += bytestream2_get_le32(gb);
      56           0 :         break;
      57           0 :     case 62:
      58           0 :         len += bytestream2_get_le24(gb);
      59           0 :         break;
      60          65 :     case 61:
      61          65 :         len += bytestream2_get_le16(gb);
      62          65 :         break;
      63         669 :     case 60:
      64         669 :         len += bytestream2_get_byte(gb);
      65         669 :         break;
      66       25910 :     default: // val < 60
      67       25910 :         len += val;
      68             :     }
      69             : 
      70       26644 :     if (size < len)
      71           0 :         return AVERROR_INVALIDDATA;
      72             : 
      73       26644 :     bytestream2_get_buffer(gb, p, len);
      74             : 
      75       26644 :     return len;
      76             : }
      77             : 
      78       33740 : static int snappy_copy(uint8_t *start, uint8_t *p, int size,
      79             :                        unsigned int off, int len)
      80             : {
      81             :     uint8_t *q;
      82             :     int i;
      83       33740 :     if (off > p - start || size < len)
      84           0 :         return AVERROR_INVALIDDATA;
      85             : 
      86       33740 :     q = p - off;
      87             : 
      88      466071 :     for (i = 0; i < len; i++)
      89      432331 :         p[i] = q[i];
      90             : 
      91       33740 :     return len;
      92             : }
      93             : 
      94       16119 : static int snappy_copy1(GetByteContext *gb, uint8_t *start, uint8_t *p,
      95             :                         int size, int val)
      96             : {
      97       16119 :     int len          = 4 + (val & 0x7);
      98       16119 :     unsigned int off = bytestream2_get_byte(gb) | (val & 0x38) << 5;
      99             : 
     100       16119 :     return snappy_copy(start, p, size, off, len);
     101             : }
     102             : 
     103       17621 : static int snappy_copy2(GetByteContext *gb, uint8_t *start, uint8_t *p,
     104             :                         int size, int val)
     105             : {
     106       17621 :     int len          = 1 + val;
     107       17621 :     unsigned int off = bytestream2_get_le16(gb);
     108             : 
     109       17621 :     return snappy_copy(start, p, size, off, len);
     110             : }
     111             : 
     112           0 : static int snappy_copy4(GetByteContext *gb, uint8_t *start, uint8_t *p,
     113             :                         int size, int val)
     114             : {
     115           0 :     int len          = 1 + val;
     116           0 :     unsigned int off = bytestream2_get_le32(gb);
     117             : 
     118           0 :     return snappy_copy(start, p, size, off, len);
     119             : }
     120             : 
     121         100 : static int64_t decode_len(GetByteContext *gb)
     122             : {
     123         100 :     int64_t len = bytestream2_get_levarint(gb);
     124             : 
     125         100 :     if (len < 0 || len > UINT_MAX)
     126           0 :         return AVERROR_INVALIDDATA;
     127             : 
     128         100 :     return len;
     129             : }
     130             : 
     131          50 : int64_t ff_snappy_peek_uncompressed_length(GetByteContext *gb)
     132             : {
     133          50 :     int pos = bytestream2_get_bytes_left(gb);
     134          50 :     int64_t len = decode_len(gb);
     135             : 
     136          50 :     bytestream2_seek(gb, -pos, SEEK_END);
     137             : 
     138          50 :     return len;
     139             : }
     140             : 
     141          50 : int ff_snappy_uncompress(GetByteContext *gb, uint8_t *buf, int64_t *size)
     142             : {
     143          50 :     int64_t len = decode_len(gb);
     144          50 :     int ret     = 0;
     145             :     uint8_t *p;
     146             : 
     147          50 :     if (len < 0)
     148           0 :         return len;
     149             : 
     150          50 :     if (len > *size)
     151           0 :         return AVERROR_BUFFER_TOO_SMALL;
     152             : 
     153          50 :     *size = len;
     154          50 :     p     = buf;
     155             : 
     156       60484 :     while (bytestream2_get_bytes_left(gb) > 0) {
     157       60384 :         uint8_t s = bytestream2_get_byte(gb);
     158       60384 :         int val   = s >> 2;
     159             : 
     160       60384 :         switch (s & 0x03) {
     161       26644 :         case SNAPPY_LITERAL:
     162       26644 :             ret = snappy_literal(gb, p, len, val);
     163       26644 :             break;
     164       16119 :         case SNAPPY_COPY_1:
     165       16119 :             ret = snappy_copy1(gb, buf, p, len, val);
     166       16119 :             break;
     167       17621 :         case SNAPPY_COPY_2:
     168       17621 :             ret = snappy_copy2(gb, buf, p, len, val);
     169       17621 :             break;
     170           0 :         case SNAPPY_COPY_4:
     171           0 :             ret = snappy_copy4(gb, buf, p, len, val);
     172           0 :             break;
     173             :         }
     174             : 
     175       60384 :         if (ret < 0)
     176           0 :             return ret;
     177             : 
     178       60384 :         p   += ret;
     179       60384 :         len -= ret;
     180             :     }
     181             : 
     182          50 :     return 0;
     183             : }

Generated by: LCOV version 1.13