Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.cc

Issue 17101030: Media Galleries API - Picasa: Change PMP Parsing to deal with PlatformFile. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h" 5 #include "chrome/browser/media_galleries/fileapi/picasa/pmp_column_reader.h"
6 6
7 #include <cstring> 7 #include <cstring>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h" 10 #include "base/logging.h"
12 #include "base/threading/thread_restrictions.h" 11 #include "base/threading/thread_restrictions.h"
13 12
14 namespace picasa { 13 namespace picasa {
15 14
16 namespace { 15 namespace {
17 16
17 COMPILE_ASSERT(sizeof(double) == 8, double_must_be_8_bytes_long);
18 const int64 kPmpMaxFilesize = 50*1024*1024; // Arbitrary maximum of 50 MB. 18 const int64 kPmpMaxFilesize = 50*1024*1024; // Arbitrary maximum of 50 MB.
19 19
20 } // namespace 20 } // namespace
21 21
22 PmpColumnReader::PmpColumnReader() 22 PmpColumnReader::PmpColumnReader()
23 : length_(0), 23 : length_(0),
24 field_type_(PMP_TYPE_INVALID), 24 field_type_(PMP_TYPE_INVALID),
25 rows_(0) {} 25 rows_read_(0) {}
26 26
27 PmpColumnReader::~PmpColumnReader() {} 27 PmpColumnReader::~PmpColumnReader() {}
28 28
29 bool PmpColumnReader::Init(const base::FilePath& filepath, 29 bool PmpColumnReader::ReadFile(base::PlatformFile file,
30 const PmpFieldType expected_type, 30 const PmpFieldType expected_type) {
31 uint32* rows_read) {
32 DCHECK(!data_.get()); 31 DCHECK(!data_.get());
33 base::ThreadRestrictions::AssertIOAllowed(); 32 base::ThreadRestrictions::AssertIOAllowed();
34 33
35 if (!file_util::GetFileSize(filepath, &length_)) 34 if (file == base::kInvalidPlatformFileValue)
36 return false; 35 return false;
37 36
37 base::PlatformFileInfo info;
38 if (!base::GetPlatformFileInfo(file, &info))
39 return false;
40 length_ = info.size;
41
38 if (length_ < kPmpHeaderSize || length_ > kPmpMaxFilesize) 42 if (length_ < kPmpHeaderSize || length_ > kPmpMaxFilesize)
39 return false; 43 return false;
40 44
41 data_.reset(new uint8[length_]); 45 data_.reset(new uint8[length_]);
42 46
43 char* data_begin = reinterpret_cast<char*>(data_.get()); 47 char* data_begin = reinterpret_cast<char*>(data_.get());
44 48
45 DCHECK(length_ < kint32max); // ReadFile expects an int. 49 DCHECK(length_ < kint32max); // ReadFile expects an int.
46 50
47 bool success = file_util::ReadFile(filepath, data_begin, length_) && 51 bool success = base::ReadPlatformFile(file, 0, data_begin, length_) &&
48 ParseData(expected_type, rows_read); 52 ParseData(expected_type);
49 53
54 // If any of the reading or parsing fails, prevent Read* calls.
50 if (!success) 55 if (!success)
51 rows_ = 0; // If any of the reading or parsing fails, prevent Read* calls. 56 rows_read_ = 0;
52 57
53 return success; 58 return success;
54 } 59 }
55 60
56 bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const { 61 bool PmpColumnReader::ReadString(const uint32 row, std::string* result) const {
57 DCHECK(data_.get() != NULL); 62 DCHECK(data_.get() != NULL);
58 63
59 if (field_type_ != PMP_TYPE_STRING || row >= rows_) 64 if (field_type_ != PMP_TYPE_STRING || row >= rows_read_)
60 return false; 65 return false;
61 66
62 DCHECK_LT(row, strings_.size()); 67 DCHECK_LT(row, strings_.size());
63 *result = strings_[row]; 68 *result = strings_[row];
64 return true; 69 return true;
65 } 70 }
66 71
67 bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const { 72 bool PmpColumnReader::ReadUInt32(const uint32 row, uint32* result) const {
68 DCHECK(data_.get() != NULL); 73 DCHECK(data_.get() != NULL);
69 74
70 if (field_type_ != PMP_TYPE_UINT32 || row >= rows_) 75 if (field_type_ != PMP_TYPE_UINT32 || row >= rows_read_)
71 return false; 76 return false;
72 77
73 *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row]; 78 *result = reinterpret_cast<uint32*>(data_.get() + kPmpHeaderSize)[row];
74 return true; 79 return true;
75 } 80 }
76 81
77 bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const { 82 bool PmpColumnReader::ReadDouble64(const uint32 row, double* result) const {
78 DCHECK(data_.get() != NULL); 83 DCHECK(data_.get() != NULL);
79 84
80 if (field_type_ != PMP_TYPE_DOUBLE64 || row >= rows_) 85 if (field_type_ != PMP_TYPE_DOUBLE64 || row >= rows_read_)
81 return false; 86 return false;
82 87
83 *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row]; 88 *result = reinterpret_cast<double*>(data_.get() + kPmpHeaderSize)[row];
84 return true; 89 return true;
85 } 90 }
86 91
87 bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const { 92 bool PmpColumnReader::ReadUInt8(const uint32 row, uint8* result) const {
88 DCHECK(data_.get() != NULL); 93 DCHECK(data_.get() != NULL);
89 94
90 if (field_type_ != PMP_TYPE_UINT8 || row >= rows_) 95 if (field_type_ != PMP_TYPE_UINT8 || row >= rows_read_)
91 return false; 96 return false;
92 97
93 *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row]; 98 *result = reinterpret_cast<uint8*>(data_.get() + kPmpHeaderSize)[row];
94 return true; 99 return true;
95 } 100 }
96 101
97 bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const { 102 bool PmpColumnReader::ReadUInt64(const uint32 row, uint64* result) const {
98 DCHECK(data_.get() != NULL); 103 DCHECK(data_.get() != NULL);
99 104
100 if (field_type_ != PMP_TYPE_UINT64 || row >= rows_) 105 if (field_type_ != PMP_TYPE_UINT64 || row >= rows_read_)
101 return false; 106 return false;
102 107
103 *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row]; 108 *result = reinterpret_cast<uint64*>(data_.get() + kPmpHeaderSize)[row];
104 return true; 109 return true;
105 } 110 }
106 111
107 bool PmpColumnReader::ParseData(const PmpFieldType expected_type, 112 uint32 PmpColumnReader::rows_read() const {
108 uint32* rows_read) { 113 DCHECK(data_.get() != NULL);
114 return rows_read_;
115 }
116
117 bool PmpColumnReader::ParseData(const PmpFieldType expected_type) {
109 DCHECK(data_.get() != NULL); 118 DCHECK(data_.get() != NULL);
110 DCHECK_GE(length_, kPmpHeaderSize); 119 DCHECK_GE(length_, kPmpHeaderSize);
111 120
112 // Check all magic bytes. 121 // Check all magic bytes.
113 if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 || 122 if (memcmp(&kPmpMagic1, &data_[kPmpMagic1Offset], sizeof(kPmpMagic1)) != 0 ||
114 memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 || 123 memcmp(&kPmpMagic2, &data_[kPmpMagic2Offset], sizeof(kPmpMagic2)) != 0 ||
115 memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 || 124 memcmp(&kPmpMagic3, &data_[kPmpMagic3Offset], sizeof(kPmpMagic3)) != 0 ||
116 memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) { 125 memcmp(&kPmpMagic4, &data_[kPmpMagic4Offset], sizeof(kPmpMagic4)) != 0) {
117 return false; 126 return false;
118 } 127 }
119 128
120 uint16 field_type_data = 129 uint16 field_type_data =
121 *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset])); 130 *(reinterpret_cast<uint16*>(&data_[kPmpFieldType1Offset]));
122 131
123 // Verify if field type matches second declaration 132 // Verify if field type matches second declaration
124 if (field_type_data != 133 if (field_type_data !=
125 *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset]))) { 134 *(reinterpret_cast<uint16*>(&data_[kPmpFieldType2Offset]))) {
126 return false; 135 return false;
127 } 136 }
128 137
129 field_type_ = static_cast<PmpFieldType>(field_type_data); 138 field_type_ = static_cast<PmpFieldType>(field_type_data);
130 139
131 if (field_type_ != expected_type) 140 if (field_type_ != expected_type)
132 return false; 141 return false;
133 142
134 rows_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset])); 143 rows_read_ = *(reinterpret_cast<uint32*>(&data_[kPmpRowCountOffset]));
135 144
136 // Sanity check against malicious row field. 145 // Sanity check against malicious row field.
137 if (rows_ > (kPmpMaxFilesize - kPmpHeaderSize)) 146 if (rows_read_ > (kPmpMaxFilesize - kPmpHeaderSize))
138 return false; 147 return false;
139 148
140 DCHECK_GE(length_, kPmpHeaderSize); 149 DCHECK_GE(length_, kPmpHeaderSize);
141 int64 body_length = length_ - kPmpHeaderSize; 150 int64 body_length = length_ - kPmpHeaderSize;
142 int64 expected_body_length = 0; 151 int64 expected_body_length = 0;
143 switch (field_type_) { 152 switch (field_type_) {
144 case PMP_TYPE_STRING: 153 case PMP_TYPE_STRING:
145 expected_body_length = IndexStrings(); 154 expected_body_length = IndexStrings();
146 break; 155 break;
147 case PMP_TYPE_UINT32: 156 case PMP_TYPE_UINT32:
148 expected_body_length = static_cast<int64>(rows_) * sizeof(uint32); 157 expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint32);
149 break; 158 break;
150 case PMP_TYPE_DOUBLE64: 159 case PMP_TYPE_DOUBLE64:
151 expected_body_length = static_cast<int64>(rows_) * sizeof(double); 160 expected_body_length = static_cast<int64>(rows_read_) * sizeof(double);
152 break; 161 break;
153 case PMP_TYPE_UINT8: 162 case PMP_TYPE_UINT8:
154 expected_body_length = static_cast<int64>(rows_) * sizeof(uint8); 163 expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint8);
155 break; 164 break;
156 case PMP_TYPE_UINT64: 165 case PMP_TYPE_UINT64:
157 expected_body_length = static_cast<int64>(rows_) * sizeof(uint64); 166 expected_body_length = static_cast<int64>(rows_read_) * sizeof(uint64);
158 break; 167 break;
159 default: 168 default:
160 return false; 169 return false;
161 break; 170 break;
162 } 171 }
163 172
164 if (body_length == expected_body_length && rows_read)
165 *rows_read = rows_;
166 return body_length == expected_body_length; 173 return body_length == expected_body_length;
167 } 174 }
168 175
169 int64 PmpColumnReader::IndexStrings() { 176 int64 PmpColumnReader::IndexStrings() {
170 DCHECK(data_.get() != NULL); 177 DCHECK(data_.get() != NULL);
171 DCHECK_GE(length_, kPmpHeaderSize); 178 DCHECK_GE(length_, kPmpHeaderSize);
172 179
173 strings_.reserve(rows_); 180 strings_.reserve(rows_read_);
174 181
175 int64 bytes_parsed = kPmpHeaderSize; 182 int64 bytes_parsed = kPmpHeaderSize;
176 const uint8* data_cursor = data_.get() + kPmpHeaderSize; 183 const uint8* data_cursor = data_.get() + kPmpHeaderSize;
177 184
178 while (strings_.size() < rows_) { 185 while (strings_.size() < rows_read_) {
179 const uint8* string_end = static_cast<const uint8*>( 186 const uint8* string_end = static_cast<const uint8*>(
180 memchr(data_cursor, '\0', length_ - bytes_parsed)); 187 memchr(data_cursor, '\0', length_ - bytes_parsed));
181 188
182 // Fail if cannot find null termination. String runs on past file end. 189 // Fail if cannot find null termination. String runs on past file end.
183 if (string_end == NULL) 190 if (string_end == NULL)
184 return -1; 191 return -1;
185 192
186 // Length of string. (+1 to include the termination character). 193 // Length of string. (+1 to include the termination character).
187 ptrdiff_t length_in_bytes = string_end - data_cursor + 1; 194 ptrdiff_t length_in_bytes = string_end - data_cursor + 1;
188 195
189 strings_.push_back(reinterpret_cast<const char*>(data_cursor)); 196 strings_.push_back(reinterpret_cast<const char*>(data_cursor));
190 data_cursor += length_in_bytes; 197 data_cursor += length_in_bytes;
191 bytes_parsed += length_in_bytes; 198 bytes_parsed += length_in_bytes;
192 } 199 }
193 200
194 return bytes_parsed - kPmpHeaderSize; 201 return bytes_parsed - kPmpHeaderSize;
195 } 202 }
196 203
197 } // namespace picasa 204 } // namespace picasa
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698