isomorphic-git 1.37.3 → 1.37.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,6 +9,7 @@ var AsyncLock = _interopDefault(require('async-lock'));
9
9
  var Hash = _interopDefault(require('sha.js/sha1.js'));
10
10
  var crc32 = _interopDefault(require('crc-32'));
11
11
  var pako = _interopDefault(require('pako'));
12
+ var crypto$1 = require('crypto');
12
13
 
13
14
  /**
14
15
  * @typedef {Object} GitProgressEvent
@@ -4037,12 +4038,13 @@ class GitPackIndex {
4037
4038
  0b1100000: 'ofs_delta',
4038
4039
  0b1110000: 'ref_delta',
4039
4040
  };
4040
- if (!this.pack) {
4041
+ const pack = await this.pack;
4042
+ if (!pack) {
4041
4043
  throw new InternalError(
4042
- 'Tried to read from a GitPackIndex with no packfile loaded into memory'
4044
+ 'Could not read packfile data. The packfile may be missing, corrupted, or too large to read into memory.'
4043
4045
  )
4044
4046
  }
4045
- const raw = (await this.pack).slice(start);
4047
+ const raw = pack.slice(start);
4046
4048
  const reader = new BufferCursor(raw);
4047
4049
  const byte = reader.readUInt8();
4048
4050
  // Object type is encoded in bits 654
@@ -4131,6 +4133,19 @@ function readPackIndex({
4131
4133
  return p
4132
4134
  }
4133
4135
 
4136
+ const SHA1_CHUNK_SIZE = 8 * 1024 * 1024;
4137
+
4138
+ async function shasumRange(
4139
+ buffer,
4140
+ { start = 0, end = buffer.length } = {}
4141
+ ) {
4142
+ const hash = crypto$1.createHash('sha1');
4143
+ for (let i = start; i < end; i += SHA1_CHUNK_SIZE) {
4144
+ hash.update(buffer.subarray(i, Math.min(i + SHA1_CHUNK_SIZE, end)));
4145
+ }
4146
+ return hash.digest('hex')
4147
+ }
4148
+
4134
4149
  async function readObjectPacked({
4135
4150
  fs,
4136
4151
  cache,
@@ -4154,12 +4169,18 @@ async function readObjectPacked({
4154
4169
  if (p.error) throw new InternalError(p.error)
4155
4170
  // If the packfile DOES have the oid we're looking for...
4156
4171
  if (p.offsets.has(oid)) {
4157
- // Get the resolved git object from the packfile
4172
+ // Derive the .pack path from the .idx path
4173
+ const packFile = indexFile.replace(/idx$/, 'pack');
4158
4174
  if (!p.pack) {
4159
- const packFile = indexFile.replace(/idx$/, 'pack');
4160
4175
  p.pack = fs.read(packFile);
4161
4176
  }
4162
4177
  const pack = await p.pack;
4178
+ if (!pack) {
4179
+ p.pack = null;
4180
+ throw new InternalError(
4181
+ `Could not read packfile at ${packFile}. The file may be missing, corrupted, or too large to read into memory.`
4182
+ )
4183
+ }
4163
4184
 
4164
4185
  // === Packfile Integrity Verification ===
4165
4186
  // Performance optimization: use _checksumVerified flag to verify only once per packfile
@@ -4178,11 +4199,12 @@ async function readObjectPacked({
4178
4199
  )
4179
4200
  }
4180
4201
 
4181
- // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload
4182
- // This ensures true data integrity by verifying the entire packfile content
4183
- // Use subarray for zero-copy reading of large files
4184
- const payload = pack.subarray(0, -20);
4185
- const actualPayloadSha = await shasum(payload);
4202
+ // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload.
4203
+ // The Node package build swaps in a chunked implementation for large packs.
4204
+ const actualPayloadSha = await shasumRange(pack, {
4205
+ start: 0,
4206
+ end: pack.length - 20,
4207
+ });
4186
4208
  if (actualPayloadSha !== expectedShaFromIndex) {
4187
4209
  throw new InternalError(
4188
4210
  `Packfile payload corrupted: calculated ${actualPayloadSha} but expected ${expectedShaFromIndex}. The packfile may have been tampered with.`
package/managers/index.js CHANGED
@@ -4031,12 +4031,13 @@ class GitPackIndex {
4031
4031
  0b1100000: 'ofs_delta',
4032
4032
  0b1110000: 'ref_delta',
4033
4033
  };
4034
- if (!this.pack) {
4034
+ const pack = await this.pack;
4035
+ if (!pack) {
4035
4036
  throw new InternalError(
4036
- 'Tried to read from a GitPackIndex with no packfile loaded into memory'
4037
+ 'Could not read packfile data. The packfile may be missing, corrupted, or too large to read into memory.'
4037
4038
  )
4038
4039
  }
4039
- const raw = (await this.pack).slice(start);
4040
+ const raw = pack.slice(start);
4040
4041
  const reader = new BufferCursor(raw);
4041
4042
  const byte = reader.readUInt8();
4042
4043
  // Object type is encoded in bits 654
@@ -4125,6 +4126,13 @@ function readPackIndex({
4125
4126
  return p
4126
4127
  }
4127
4128
 
4129
+ async function shasumRange(
4130
+ buffer,
4131
+ { start = 0, end = buffer.length } = {}
4132
+ ) {
4133
+ return shasum(buffer.subarray(start, end))
4134
+ }
4135
+
4128
4136
  async function readObjectPacked({
4129
4137
  fs,
4130
4138
  cache,
@@ -4148,12 +4156,18 @@ async function readObjectPacked({
4148
4156
  if (p.error) throw new InternalError(p.error)
4149
4157
  // If the packfile DOES have the oid we're looking for...
4150
4158
  if (p.offsets.has(oid)) {
4151
- // Get the resolved git object from the packfile
4159
+ // Derive the .pack path from the .idx path
4160
+ const packFile = indexFile.replace(/idx$/, 'pack');
4152
4161
  if (!p.pack) {
4153
- const packFile = indexFile.replace(/idx$/, 'pack');
4154
4162
  p.pack = fs.read(packFile);
4155
4163
  }
4156
4164
  const pack = await p.pack;
4165
+ if (!pack) {
4166
+ p.pack = null;
4167
+ throw new InternalError(
4168
+ `Could not read packfile at ${packFile}. The file may be missing, corrupted, or too large to read into memory.`
4169
+ )
4170
+ }
4157
4171
 
4158
4172
  // === Packfile Integrity Verification ===
4159
4173
  // Performance optimization: use _checksumVerified flag to verify only once per packfile
@@ -4172,11 +4186,12 @@ async function readObjectPacked({
4172
4186
  )
4173
4187
  }
4174
4188
 
4175
- // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload
4176
- // This ensures true data integrity by verifying the entire packfile content
4177
- // Use subarray for zero-copy reading of large files
4178
- const payload = pack.subarray(0, -20);
4179
- const actualPayloadSha = await shasum(payload);
4189
+ // 2. Deep Integrity Check: Calculate actual SHA-1 of packfile payload.
4190
+ // The Node package build swaps in a chunked implementation for large packs.
4191
+ const actualPayloadSha = await shasumRange(pack, {
4192
+ start: 0,
4193
+ end: pack.length - 20,
4194
+ });
4180
4195
  if (actualPayloadSha !== expectedShaFromIndex) {
4181
4196
  throw new InternalError(
4182
4197
  `Packfile payload corrupted: calculated ${actualPayloadSha} but expected ${expectedShaFromIndex}. The packfile may have been tampered with.`