File: sandboxed_file.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (190 lines) | stat: -rw-r--r-- 5,450 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/persistent_cache/sqlite/vfs/sandboxed_file.h"

#include "base/numerics/safe_conversions.h"
#include "third_party/sqlite/sqlite3.h"

namespace persistent_cache {

SandboxedFile::SandboxedFile(base::File file, AccessRights access_rights)
    : underlying_file_(std::move(file)),
      access_rights_(access_rights),
      sqlite_lock_mode_(SQLITE_LOCK_NONE) {}
SandboxedFile::~SandboxedFile() = default;

base::File SandboxedFile::TakeUnderlyingFile() {
  return std::move(underlying_file_);
}

void SandboxedFile::OnFileOpened(base::File file) {
  CHECK(file.IsValid());
  opened_file_ = std::move(file);
}

int SandboxedFile::Close() {
  CHECK(IsValid());
  underlying_file_ = std::move(opened_file_);
  return SQLITE_OK;
}

int SandboxedFile::Read(void* buffer, int size, sqlite3_int64 offset) {
  // Make a safe span from the pair <buffer, size>. The buffer and the
  // size are received from sqlite.
  CHECK(buffer);
  CHECK_GE(size, 0);
  CHECK_GE(offset, 0);
  const size_t checked_size = base::checked_cast<size_t>(size);
  // SAFETY: `buffer` always points to at least `size` valid bytes.
  auto data =
      UNSAFE_BUFFERS(base::span(static_cast<uint8_t*>(buffer), checked_size));

  // Read data from the file.
  CHECK(IsValid());
  std::optional<size_t> bytes_read = opened_file_.Read(offset, data);
  if (!bytes_read.has_value()) {
    return SQLITE_IOERR_READ;
  }

  // The buffer was fully read.
  if (bytes_read.value() == checked_size) {
    return SQLITE_OK;
  }

  // Some bytes were read but the buffer was not filled. SQLite requires that
  // the unread bytes must be filled with zeros.
  auto remaining_bytes = data.subspan(bytes_read.value());
  std::fill(remaining_bytes.begin(), remaining_bytes.end(), 0);
  return SQLITE_IOERR_SHORT_READ;
}

int SandboxedFile::Write(const void* buffer, int size, sqlite3_int64 offset) {
  // Make a safe span from the pair <buffer, size>. The buffer and the
  // size are received from sqlite.
  CHECK(buffer);
  CHECK_GE(size, 0);
  CHECK_GE(offset, 0);
  const size_t checked_size = base::checked_cast<size_t>(size);
  // SAFETY: `buffer` always points to at least `size` valid bytes.
  auto data = UNSAFE_BUFFERS(
      base::span(static_cast<const uint8_t*>(buffer), checked_size));

  CHECK(IsValid());
  std::optional<size_t> bytes_written = opened_file_.Write(offset, data);
  if (!bytes_written.has_value()) {
    return SQLITE_IOERR_WRITE;
  }
  CHECK_LE(bytes_written.value(), checked_size);

  // The bytes were successfully written to disk.
  if (bytes_written.value() == checked_size) {
    return SQLITE_OK;
  }

  // Detect the case where there is no space on the disk.
  base::File::Error last_error = base::File::GetLastFileError();
  if (last_error == base::File::Error::FILE_ERROR_NO_SPACE) {
    return SQLITE_FULL;
  }

  // A generic write error.
  return SQLITE_IOERR_WRITE;
}

int SandboxedFile::Truncate(sqlite3_int64 size) {
  CHECK(IsValid());
  if (!opened_file_.SetLength(size)) {
    return SQLITE_IOERR_TRUNCATE;
  }
  return SQLITE_OK;
}

int SandboxedFile::Sync(int flags) {
  CHECK(IsValid());
  if (!opened_file_.Flush()) {
    return SQLITE_IOERR_FSYNC;
  }
  return SQLITE_OK;
}

int SandboxedFile::FileSize(sqlite3_int64* result_size) {
  CHECK(IsValid());
  int64_t length = opened_file_.GetLength();
  if (length < 0) {
    return SQLITE_IOERR_FSTAT;
  }

  *result_size = length;
  return SQLITE_OK;
}

int SandboxedFile::Lock(int mode) {
  // TODO(https://crbug.com/377475540): Implement a cross-process lock.
  if (mode > sqlite_lock_mode_) {
    sqlite_lock_mode_ = mode;
  }
  return SQLITE_OK;
}

int SandboxedFile::Unlock(int mode) {
  // TODO(https://crbug.com/377475540): Implement a cross-process lock.
  if (mode < sqlite_lock_mode_) {
    sqlite_lock_mode_ = mode;
  }
  return SQLITE_OK;
}

int SandboxedFile::CheckReservedLock(int* has_reserved_lock) {
  // TODO(https://crbug.com/377475540): Implement a cross-process lock.
  *has_reserved_lock = sqlite_lock_mode_ >= SQLITE_LOCK_RESERVED;
  return SQLITE_OK;
}

int SandboxedFile::FileControl(int opcode, void* data) {
  return SQLITE_NOTFOUND;
}

int SandboxedFile::SectorSize() {
  return 0;
}

int SandboxedFile::DeviceCharacteristics() {
  return 0;
}

int SandboxedFile::ShmMap(int page_index,
                          int page_size,
                          int extend_file_if_needed,
                          void volatile** result) {
  // TODO(https://crbug.com/377475540): Implement WAL mode.
  return SQLITE_IOERR_SHMMAP;
}

int SandboxedFile::ShmLock(int offset, int size, int flags) {
  // TODO(https://crbug.com/377475540): Implement WAL mode.
  return SQLITE_IOERR_SHMLOCK;
}

void SandboxedFile::ShmBarrier() {
  // TODO(https://crbug.com/377475540): Implement WAL mode.
}

int SandboxedFile::ShmUnmap(int also_delete_file) {
  // TODO(https://crbug.com/377475540): Implement WAL mode.
  return SQLITE_IOERR_SHMMAP;
}

int SandboxedFile::Fetch(sqlite3_int64 offset, int size, void** result) {
  // TODO(https://crbug.com/377475540): Implement shared memory.
  *result = nullptr;
  return SQLITE_IOERR;
}

int SandboxedFile::Unfetch(sqlite3_int64 offset, void* fetch_result) {
  // TODO(https://crbug.com/377475540): Implement shared memory.
  return SQLITE_IOERR;
}

}  // namespace persistent_cache