1 // Copyright 2018 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/process/process_memory.h"
16
17 #include <string.h>
18
19 #include <algorithm>
20
21 #include "base/check_op.h"
22 #include "base/logging.h"
23 #include "util/numeric/safe_assignment.h"
24
25 namespace crashpad {
26
Read(VMAddress address,VMSize size,void * buffer) const27 bool ProcessMemory::Read(VMAddress address, VMSize size, void* buffer) const {
28 size_t local_size;
29 if (!AssignIfInRange(&local_size, size)) {
30 LOG(ERROR) << "size " << size << " out of bounds for size_t";
31 return false;
32 }
33
34 char* buffer_c = static_cast<char*>(buffer);
35 while (local_size > 0) {
36 ssize_t bytes_read = ReadUpTo(address, local_size, buffer_c);
37 if (bytes_read < 0) {
38 return false;
39 }
40 if (bytes_read == 0) {
41 LOG(ERROR) << "short read";
42 return false;
43 }
44 DCHECK_LE(static_cast<size_t>(bytes_read), local_size);
45 local_size -= bytes_read;
46 address += bytes_read;
47 buffer_c += bytes_read;
48 }
49 return true;
50 }
51
ReadCStringInternal(VMAddress address,bool has_size,VMSize size,std::string * string) const52 bool ProcessMemory::ReadCStringInternal(VMAddress address,
53 bool has_size,
54 VMSize size,
55 std::string* string) const {
56 size_t local_size;
57 if (!AssignIfInRange(&local_size, size)) {
58 LOG(ERROR) << "size " << size << " out of bounds for size_t";
59 return false;
60 }
61
62 string->clear();
63
64 char buffer[4096];
65 do {
66 size_t read_size;
67 if (has_size) {
68 read_size = std::min(sizeof(buffer), local_size);
69 } else {
70 read_size = sizeof(buffer);
71 }
72
73 ssize_t bytes_read = ReadUpTo(address, read_size, buffer);
74 if (bytes_read < 0) {
75 return false;
76 }
77 if (bytes_read == 0) {
78 break;
79 }
80
81 char* nul = static_cast<char*>(memchr(buffer, '\0', bytes_read));
82 if (nul != nullptr) {
83 string->append(buffer, nul - buffer);
84 return true;
85 }
86 string->append(buffer, bytes_read);
87
88 address += bytes_read;
89 local_size -= bytes_read;
90 } while (!has_size || local_size > 0);
91
92 LOG(ERROR) << "unterminated string";
93 return false;
94 }
95
96 } // namespace crashpad
97