FoFiBase.cc 4.46 KB
Newer Older
Kristian Høgsberg's avatar
Kristian Høgsberg committed
1 2 3 4 5 6 7 8
//========================================================================
//
// FoFiBase.cc
//
// Copyright 1999-2003 Glyph & Cog, LLC
//
//========================================================================

9 10 11 12
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
13 14 15
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
16
// Copyright (C) 2008 Ed Avis <eda@waniasset.com>
Albert Astals Cid's avatar
Albert Astals Cid committed
17
// Copyright (C) 2011 Jim Meyering <jim@meyering.net>
Albert Astals Cid's avatar
Albert Astals Cid committed
18
// Copyright (C) 2016, 2018 Albert Astals Cid <aacid@kde.org>
19
// Copyright (C) 2019 Christian Persch <chpe@src.gnome.org>
20
// Copyright (C) 2019 LE GARREC Vincent <legarrec.vincent@gmail.com>
21 22 23 24 25 26
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================

Kristian Høgsberg's avatar
Kristian Høgsberg committed
27 28 29
#include <config.h>

#include <stdio.h>
30
#include <limits.h>
31
#include "goo/gfile.h"
Kristian Høgsberg's avatar
Kristian Høgsberg committed
32
#include "goo/gmem.h"
Albert Astals Cid's avatar
Albert Astals Cid committed
33
#include "poppler/Error.h"
Kristian Høgsberg's avatar
Kristian Høgsberg committed
34 35 36 37 38 39
#include "FoFiBase.h"

//------------------------------------------------------------------------
// FoFiBase
//------------------------------------------------------------------------

40
FoFiBase::FoFiBase(const char *fileA, int lenA, bool freeFileDataA) {
41
  file = (const unsigned char *)fileA;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
42 43 44 45 46 47
  len = lenA;
  freeFileData = freeFileDataA;
}

FoFiBase::~FoFiBase() {
  if (freeFileData) {
48
    gfree((char*)file);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
49 50 51
  }
}

52
char *FoFiBase::readFile(const char *fileName, int *fileLen) {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
53 54 55 56
  FILE *f;
  char *buf;
  int n;

57
  if (!(f = openFile(fileName, "rb"))) {
58
    error(errIO, -1, "Cannot open '{0:s}'", fileName);
59
    return nullptr;
Ed Avis's avatar
Ed Avis committed
60 61
  }
  if (fseek(f, 0, SEEK_END) != 0) {
62
    error(errIO, -1, "Cannot seek to end of '{0:s}'", fileName);
Ed Avis's avatar
Ed Avis committed
63
    fclose(f);
64
    return nullptr;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
65 66
  }
  n = (int)ftell(f);
67
  if (n < 0) {
68
    error(errIO, -1, "Cannot determine length of '{0:s}'", fileName);
69
    fclose(f);
70
    return nullptr;
71
  }
Ed Avis's avatar
Ed Avis committed
72
  if (fseek(f, 0, SEEK_SET) != 0) {
73
    error(errIO, -1, "Cannot seek to start of '{0:s}'", fileName);
Ed Avis's avatar
Ed Avis committed
74
    fclose(f);
75
    return nullptr;
Ed Avis's avatar
Ed Avis committed
76
  }
Kristian Høgsberg's avatar
Kristian Høgsberg committed
77 78 79 80
  buf = (char *)gmalloc(n);
  if ((int)fread(buf, 1, n, f) != n) {
    gfree(buf);
    fclose(f);
81
    return nullptr;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
82 83 84 85 86 87
  }
  fclose(f);
  *fileLen = n;
  return buf;
}

88
int FoFiBase::getS8(int pos, bool *ok) const {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
89 90 91
  int x;

  if (pos < 0 || pos >= len) {
92
    *ok = false;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
93 94 95 96 97 98 99 100 101
    return 0;
  }
  x = file[pos];
  if (x & 0x80) {
    x |= ~0xff;
  }
  return x;
}

102
int FoFiBase::getU8(int pos, bool *ok) const {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
103
  if (pos < 0 || pos >= len) {
104
    *ok = false;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
105 106 107 108 109
    return 0;
  }
  return file[pos];
}

110
int FoFiBase::getS16BE(int pos, bool *ok) const {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
111 112
  int x;

113
  if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
114
    *ok = false;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
115 116 117 118 119 120 121 122 123 124
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  if (x & 0x8000) {
    x |= ~0xffff;
  }
  return x;
}

125
int FoFiBase::getU16BE(int pos, bool *ok) const {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
126 127
  int x;

128
  if (pos < 0 || pos+1 >= len || pos > INT_MAX - 1) {
129
    *ok = false;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
130 131 132 133 134 135 136
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  return x;
}

137
int FoFiBase::getS32BE(int pos, bool *ok) const {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
138 139
  int x;

140
  if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
141
    *ok = false;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
142 143 144 145 146 147 148 149 150 151 152 153
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  x = (x << 8) + file[pos+2];
  x = (x << 8) + file[pos+3];
  if (x & 0x80000000) {
    x |= ~0xffffffff;
  }
  return x;
}

Oliver Sander's avatar
Oliver Sander committed
154 155
unsigned int FoFiBase::getU32BE(int pos, bool *ok) const {
  unsigned int x;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
156

157
  if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
158
    *ok = false;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
159 160 161 162 163 164 165 166 167
    return 0;
  }
  x = file[pos];
  x = (x << 8) + file[pos+1];
  x = (x << 8) + file[pos+2];
  x = (x << 8) + file[pos+3];
  return x;
}

Oliver Sander's avatar
Oliver Sander committed
168 169
unsigned int FoFiBase::getU32LE(int pos, bool *ok) const {
  unsigned int x;
170 171

  if (pos < 0 || pos+3 >= len || pos > INT_MAX - 3) {
172
    *ok = false;
173 174 175 176 177 178 179 180 181
    return 0;
  }
  x = file[pos+3];
  x = (x << 8) + file[pos+2];
  x = (x << 8) + file[pos+1];
  x = (x << 8) + file[pos];
  return x;
}

Oliver Sander's avatar
Oliver Sander committed
182 183
unsigned int FoFiBase::getUVarBE(int pos, int size, bool *ok) const {
  unsigned int x;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
184 185
  int i;

186
  if (pos < 0 || pos + size > len || pos > INT_MAX - size) {
187
    *ok = false;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
188 189 190 191 192 193 194 195 196
    return 0;
  }
  x = 0;
  for (i = 0; i < size; ++i) {
    x = (x << 8) + file[pos + i];
  }
  return x;
}

197
bool FoFiBase::checkRegion(int pos, int size) const {
Kristian Høgsberg's avatar
Kristian Høgsberg committed
198
  return pos >= 0 &&
199
         size >= 0 &&
200 201
         pos < INT_MAX - size &&
         size < INT_MAX - pos &&
Kristian Høgsberg's avatar
Kristian Høgsberg committed
202 203 204
         pos + size >= pos &&
         pos + size <= len;
}