• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcodec/jpx/jpx_decode_utils.h"
8 
9 #include <stddef.h>
10 #include <string.h>
11 
12 #include <algorithm>
13 #include <limits>
14 #include <type_traits>
15 
16 namespace fxcodec {
17 
opj_read_from_memory(void * p_buffer,OPJ_SIZE_T nb_bytes,void * p_user_data)18 OPJ_SIZE_T opj_read_from_memory(void* p_buffer,
19                                 OPJ_SIZE_T nb_bytes,
20                                 void* p_user_data) {
21   DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
22   if (!srcData || !srcData->src_data || srcData->src_size == 0)
23     return static_cast<OPJ_SIZE_T>(-1);
24 
25   // Reads at EOF return an error code.
26   if (srcData->offset >= srcData->src_size)
27     return static_cast<OPJ_SIZE_T>(-1);
28 
29   OPJ_SIZE_T bufferLength = srcData->src_size - srcData->offset;
30   OPJ_SIZE_T readlength = nb_bytes < bufferLength ? nb_bytes : bufferLength;
31   memcpy(p_buffer, &srcData->src_data[srcData->offset], readlength);
32   srcData->offset += readlength;
33   return readlength;
34 }
35 
opj_skip_from_memory(OPJ_OFF_T nb_bytes,void * p_user_data)36 OPJ_OFF_T opj_skip_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) {
37   DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
38   if (!srcData || !srcData->src_data || srcData->src_size == 0)
39     return static_cast<OPJ_OFF_T>(-1);
40 
41   // Offsets are signed and may indicate a negative skip. Do not support this
42   // because of the strange return convention where either bytes skipped or
43   // -1 is returned. Following that convention, a successful relative seek of
44   // -1 bytes would be required to to give the same result as the error case.
45   if (nb_bytes < 0)
46     return static_cast<OPJ_OFF_T>(-1);
47 
48   auto unsigned_nb_bytes =
49       static_cast<std::make_unsigned<OPJ_OFF_T>::type>(nb_bytes);
50   // Additionally, the offset may take us beyond the range of a size_t (e.g.
51   // 32-bit platforms). If so, just clamp at EOF.
52   if (unsigned_nb_bytes >
53       std::numeric_limits<OPJ_SIZE_T>::max() - srcData->offset) {
54     srcData->offset = srcData->src_size;
55   } else {
56     OPJ_SIZE_T checked_nb_bytes = static_cast<OPJ_SIZE_T>(unsigned_nb_bytes);
57     // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
58     // clamping at EOF.  We can get away with this since we don't actually
59     // provide negative relative skips from beyond EOF back to inside the
60     // data, which would be the only reason to need to know exactly how far
61     // beyond EOF we are.
62     srcData->offset =
63         std::min(srcData->offset + checked_nb_bytes, srcData->src_size);
64   }
65   return nb_bytes;
66 }
67 
opj_seek_from_memory(OPJ_OFF_T nb_bytes,void * p_user_data)68 OPJ_BOOL opj_seek_from_memory(OPJ_OFF_T nb_bytes, void* p_user_data) {
69   DecodeData* srcData = static_cast<DecodeData*>(p_user_data);
70   if (!srcData || !srcData->src_data || srcData->src_size == 0)
71     return OPJ_FALSE;
72 
73   // Offsets are signed and may indicate a negative position, which would
74   // be before the start of the file. Do not support this.
75   if (nb_bytes < 0)
76     return OPJ_FALSE;
77 
78   auto unsigned_nb_bytes =
79       static_cast<std::make_unsigned<OPJ_OFF_T>::type>(nb_bytes);
80   // Additionally, the offset may take us beyond the range of a size_t (e.g.
81   // 32-bit platforms). If so, just clamp at EOF.
82   if (unsigned_nb_bytes > std::numeric_limits<OPJ_SIZE_T>::max()) {
83     srcData->offset = srcData->src_size;
84   } else {
85     OPJ_SIZE_T checked_nb_bytes = static_cast<OPJ_SIZE_T>(nb_bytes);
86     // Otherwise, mimic fseek() semantics to always succeed, even past EOF,
87     // again clamping at EOF.
88     srcData->offset = std::min(checked_nb_bytes, srcData->src_size);
89   }
90   return OPJ_TRUE;
91 }
92 
93 }  // namespace fxcodec
94