Skip to content

Commit 75b975e

Browse files
gitsterdscho
authored andcommitted
Merge branch 'jk/pack-header-parse-alignment-fix'
It was possible for "git unpack-objects" and "git index-pack" to make an unaligned access, which has been corrected. * jk/pack-header-parse-alignment-fix: index-pack, unpack-objects: use skip_prefix to avoid magic number index-pack, unpack-objects: use get_be32() for reading pack header parse_pack_header_option(): avoid unaligned memory writes packfile: factor out --pack_header argument parsing bswap.h: squelch potential sparse -Wcast-truncate warnings These patches have actually been rebased onto v2.46.2 for easier merging. Signed-off-by: Johannes Schindelin <[email protected]>
2 parents 8f74ea9 + 0d4ed91 commit 75b975e

File tree

6 files changed

+64
-50
lines changed

6 files changed

+64
-50
lines changed

builtin/index-pack.c

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -379,16 +379,18 @@ static const char *open_pack_file(const char *pack_name)
379379

380380
static void parse_pack_header(void)
381381
{
382-
struct pack_header *hdr = fill(sizeof(struct pack_header));
382+
unsigned char *hdr = fill(sizeof(struct pack_header));
383383

384384
/* Header consistency check */
385-
if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
385+
if (get_be32(hdr) != PACK_SIGNATURE)
386386
die(_("pack signature mismatch"));
387-
if (!pack_version_ok(hdr->hdr_version))
387+
hdr += 4;
388+
if (!pack_version_ok_native(get_be32(hdr)))
388389
die(_("pack version %"PRIu32" unsupported"),
389-
ntohl(hdr->hdr_version));
390+
get_be32(hdr));
391+
hdr += 4;
390392

391-
nr_objects = ntohl(hdr->hdr_entries);
393+
nr_objects = get_be32(hdr);
392394
use(sizeof(struct pack_header));
393395
}
394396

@@ -1954,19 +1956,11 @@ int cmd_index_pack(int argc,
19541956
warning(_("no threads support, ignoring %s"), arg);
19551957
nr_threads = 1;
19561958
}
1957-
} else if (starts_with(arg, "--pack_header=")) {
1958-
struct pack_header *hdr;
1959-
char *c;
1960-
1961-
hdr = (struct pack_header *)input_buffer;
1962-
hdr->hdr_signature = htonl(PACK_SIGNATURE);
1963-
hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
1964-
if (*c != ',')
1965-
die(_("bad %s"), arg);
1966-
hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
1967-
if (*c)
1968-
die(_("bad %s"), arg);
1969-
input_len = sizeof(*hdr);
1959+
} else if (skip_prefix(arg, "--pack_header=", &arg)) {
1960+
if (parse_pack_header_option(arg,
1961+
input_buffer,
1962+
&input_len) < 0)
1963+
die(_("bad --pack_header: %s"), arg);
19701964
} else if (!strcmp(arg, "-v")) {
19711965
verbose = 1;
19721966
} else if (!strcmp(arg, "--progress-title")) {

builtin/unpack-objects.c

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "progress.h"
1919
#include "decorate.h"
2020
#include "fsck.h"
21+
#include "packfile.h"
2122

2223
static int dry_run, quiet, recover, has_errors, strict;
2324
static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]";
@@ -578,15 +579,16 @@ static void unpack_one(unsigned nr)
578579
static void unpack_all(void)
579580
{
580581
int i;
581-
struct pack_header *hdr = fill(sizeof(struct pack_header));
582+
unsigned char *hdr = fill(sizeof(struct pack_header));
582583

583-
nr_objects = ntohl(hdr->hdr_entries);
584-
585-
if (ntohl(hdr->hdr_signature) != PACK_SIGNATURE)
584+
if (get_be32(hdr) != PACK_SIGNATURE)
586585
die("bad pack file");
587-
if (!pack_version_ok(hdr->hdr_version))
586+
hdr += 4;
587+
if (!pack_version_ok_native(get_be32(hdr)))
588588
die("unknown pack file version %"PRIu32,
589-
ntohl(hdr->hdr_version));
589+
get_be32(hdr));
590+
hdr += 4;
591+
nr_objects = get_be32(hdr);
590592
use(sizeof(struct pack_header));
591593

592594
if (!quiet)
@@ -644,19 +646,10 @@ int cmd_unpack_objects(int argc,
644646
fsck_set_msg_types(&fsck_options, arg);
645647
continue;
646648
}
647-
if (starts_with(arg, "--pack_header=")) {
648-
struct pack_header *hdr;
649-
char *c;
650-
651-
hdr = (struct pack_header *)buffer;
652-
hdr->hdr_signature = htonl(PACK_SIGNATURE);
653-
hdr->hdr_version = htonl(strtoul(arg + 14, &c, 10));
654-
if (*c != ',')
655-
die("bad %s", arg);
656-
hdr->hdr_entries = htonl(strtoul(c + 1, &c, 10));
657-
if (*c)
658-
die("bad %s", arg);
659-
len = sizeof(*hdr);
649+
if (skip_prefix(arg, "--pack_header=", &arg)) {
650+
if (parse_pack_header_option(arg,
651+
buffer, &len) < 0)
652+
die(_("bad --pack_header: %s"), arg);
660653
continue;
661654
}
662655
if (skip_prefix(arg, "--max-input-size=", &arg)) {

compat/bswap.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -171,23 +171,23 @@ static inline uint64_t get_be64(const void *ptr)
171171
static inline void put_be32(void *ptr, uint32_t value)
172172
{
173173
unsigned char *p = ptr;
174-
p[0] = value >> 24;
175-
p[1] = value >> 16;
176-
p[2] = value >> 8;
177-
p[3] = value >> 0;
174+
p[0] = (value >> 24) & 0xff;
175+
p[1] = (value >> 16) & 0xff;
176+
p[2] = (value >> 8) & 0xff;
177+
p[3] = (value >> 0) & 0xff;
178178
}
179179

180180
static inline void put_be64(void *ptr, uint64_t value)
181181
{
182182
unsigned char *p = ptr;
183-
p[0] = value >> 56;
184-
p[1] = value >> 48;
185-
p[2] = value >> 40;
186-
p[3] = value >> 32;
187-
p[4] = value >> 24;
188-
p[5] = value >> 16;
189-
p[6] = value >> 8;
190-
p[7] = value >> 0;
183+
p[0] = (value >> 56) & 0xff;
184+
p[1] = (value >> 48) & 0xff;
185+
p[2] = (value >> 40) & 0xff;
186+
p[3] = (value >> 32) & 0xff;
187+
p[4] = (value >> 24) & 0xff;
188+
p[5] = (value >> 16) & 0xff;
189+
p[6] = (value >> 8) & 0xff;
190+
p[7] = (value >> 0) & 0xff;
191191
}
192192

193193
#endif /* COMPAT_BSWAP_H */

pack.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ struct repository;
1313
*/
1414
#define PACK_SIGNATURE 0x5041434b /* "PACK" */
1515
#define PACK_VERSION 2
16-
#define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3))
16+
#define pack_version_ok(v) pack_version_ok_native(ntohl(v))
17+
#define pack_version_ok_native(v) ((v) == 2 || (v) == 3)
1718
struct pack_header {
1819
uint32_t hdr_signature;
1920
uint32_t hdr_version;

packfile.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2315,3 +2315,23 @@ int is_promisor_object(struct repository *r, const struct object_id *oid)
23152315
}
23162316
return oidset_contains(&promisor_objects, oid);
23172317
}
2318+
2319+
int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len)
2320+
{
2321+
unsigned char *hdr;
2322+
char *c;
2323+
2324+
hdr = out;
2325+
put_be32(hdr, PACK_SIGNATURE);
2326+
hdr += 4;
2327+
put_be32(hdr, strtoul(in, &c, 10));
2328+
hdr += 4;
2329+
if (*c != ',')
2330+
return -1;
2331+
put_be32(hdr, strtoul(c + 1, &c, 10));
2332+
hdr += 4;
2333+
if (*c)
2334+
return -1;
2335+
*len = hdr - out;
2336+
return 0;
2337+
}

packfile.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,10 @@ int is_promisor_object(struct repository *r, const struct object_id *oid);
216216
int load_idx(const char *path, const unsigned int hashsz, void *idx_map,
217217
size_t idx_size, struct packed_git *p);
218218

219+
/*
220+
* Parse a --pack_header option as accepted by index-pack and unpack-objects,
221+
* turning it into the matching bytes we'd find in a pack.
222+
*/
223+
int parse_pack_header_option(const char *in, unsigned char *out, unsigned int *len);
224+
219225
#endif

0 commit comments

Comments
 (0)