]> git.ipfire.org Git - thirdparty/squid.git/blob - src/StoreMetaUnpacker.cc
Docs: Copyright updates for 2018 (#114)
[thirdparty/squid.git] / src / StoreMetaUnpacker.cc
1 /*
2 * Copyright (C) 1996-2018 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 20 Storage Manager Swapfile Unpacker */
10
11 #include "squid.h"
12 #include "base/TextException.h"
13 #include "Debug.h"
14 #include "defines.h"
15 #include "StoreMeta.h"
16 #include "StoreMetaUnpacker.h"
17
18 int const StoreMetaUnpacker::MinimumBufferLength = sizeof(char) + sizeof(int);
19
20 /// useful for meta stored in pre-initialized (with zeros) db files
21 bool
22 StoreMetaUnpacker::isBufferZero()
23 {
24 // We could memcmp the entire buffer, but it is probably safe enough
25 // to test a few bytes because if we do not detect a corrupted entry
26 // it is not a big deal. Empty entries are not isBufferSane anyway.
27 const int depth = 10;
28 if (buflen < depth)
29 return false; // cannot be sure enough
30
31 for (int i = 0; i < depth; ++i) {
32 if (buf[i])
33 return false;
34 }
35 return true;
36 }
37
38 void
39 StoreMetaUnpacker::checkBuffer()
40 {
41 assert(buf); // paranoid; already checked in the constructor
42 if (buf[0] != static_cast<char>(STORE_META_OK))
43 throw TexcHere("store entry metadata is corrupted");
44 /*
45 * sanity check on 'buflen' value. It should be at least big
46 * enough to hold one type and one length.
47 */
48 getBufferLength();
49 if (*hdr_len < MinimumBufferLength)
50 throw TexcHere("store entry metadata is too small");
51 if (*hdr_len > buflen)
52 throw TexcHere("store entry metadata is too big");
53 }
54
55 void
56 StoreMetaUnpacker::getBufferLength()
57 {
58 memcpy(hdr_len, &buf[1], sizeof(int));
59 }
60
61 StoreMetaUnpacker::StoreMetaUnpacker(char const *aBuffer, ssize_t aLen, int *anInt) :
62 buf(aBuffer),
63 buflen(aLen),
64 hdr_len(anInt),
65 position(1 + sizeof(int)),
66 type('\0'),
67 length(0),
68 tail(NULL)
69 {
70 assert(aBuffer != NULL);
71 }
72
73 void
74 StoreMetaUnpacker::getType()
75 {
76 type = buf[position];
77 ++position;
78 }
79
80 void
81 StoreMetaUnpacker::getLength()
82 {
83 memcpy(&length, &buf[position], sizeof(int));
84 position += sizeof(int);
85 }
86
87 bool
88 StoreMetaUnpacker::doOneEntry()
89 {
90 getType();
91 getLength();
92
93 if (position + length > *hdr_len) {
94 debugs(20, DBG_CRITICAL, "storeSwapMetaUnpack: overflow!");
95 debugs(20, DBG_CRITICAL, "\ttype=" << type << ", length=" << length << ", *hdr_len=" << *hdr_len << ", offset=" << position);
96 return false;
97 }
98
99 StoreMeta *newNode = StoreMeta::Factory(type, length, &buf[position]);
100
101 if (newNode)
102 tail = StoreMeta::Add (tail, newNode);
103
104 position += length;
105
106 return true;
107 }
108
109 bool
110 StoreMetaUnpacker::moreToProcess() const
111 {
112 return *hdr_len - position - MinimumBufferLength >= 0;
113 }
114
115 StoreMeta *
116 StoreMetaUnpacker::createStoreMeta ()
117 {
118 tlv *TLV = NULL;
119 tail = &TLV;
120 assert(hdr_len != NULL);
121
122 checkBuffer();
123
124 getBufferLength();
125
126 assert (position == 1 + sizeof(int));
127
128 while (moreToProcess()) {
129 if (!doOneEntry())
130 break;
131 }
132
133 if (!TLV)
134 throw TexcHere("store entry metadata is empty");
135
136 assert(TLV);
137 return TLV;
138 }
139