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