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