@@ -1873,17 +1873,28 @@ static int read_index_extension(struct index_state *istate,
18731873 return 0 ;
18741874}
18751875
1876+ /*
1877+ * Parses the contents of the cache entry contained within the 'ondisk' buffer
1878+ * into a new incore 'cache_entry'.
1879+ *
1880+ * Note that 'char *ondisk' may not be aligned to a 4-byte address interval in
1881+ * index v4, so we cannot cast it to 'struct ondisk_cache_entry *' and access
1882+ * its members. Instead, we use the byte offsets of members within the struct to
1883+ * identify where 'get_be16()', 'get_be32()', and 'oidread()' (which can all
1884+ * read from an unaligned memory buffer) should read from the 'ondisk' buffer
1885+ * into the corresponding incore 'cache_entry' members.
1886+ */
18761887static struct cache_entry * create_from_disk (struct mem_pool * ce_mem_pool ,
18771888 unsigned int version ,
1878- struct ondisk_cache_entry * ondisk ,
1889+ const char * ondisk ,
18791890 unsigned long * ent_size ,
18801891 const struct cache_entry * previous_ce )
18811892{
18821893 struct cache_entry * ce ;
18831894 size_t len ;
18841895 const char * name ;
18851896 const unsigned hashsz = the_hash_algo -> rawsz ;
1886- const uint16_t * flagsp = ( const uint16_t * )( ondisk -> data + hashsz ) ;
1897+ const char * flagsp = ondisk + offsetof( struct ondisk_cache_entry , data ) + hashsz ;
18871898 unsigned int flags ;
18881899 size_t copy_len = 0 ;
18891900 /*
@@ -1901,15 +1912,15 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
19011912
19021913 if (flags & CE_EXTENDED ) {
19031914 int extended_flags ;
1904- extended_flags = get_be16 (flagsp + 1 ) << 16 ;
1915+ extended_flags = get_be16 (flagsp + sizeof ( uint16_t ) ) << 16 ;
19051916 /* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
19061917 if (extended_flags & ~CE_EXTENDED_FLAGS )
19071918 die (_ ("unknown index entry format 0x%08x" ), extended_flags );
19081919 flags |= extended_flags ;
1909- name = (const char * )(flagsp + 2 );
1920+ name = (const char * )(flagsp + 2 * sizeof ( uint16_t ) );
19101921 }
19111922 else
1912- name = (const char * )(flagsp + 1 );
1923+ name = (const char * )(flagsp + sizeof ( uint16_t ) );
19131924
19141925 if (expand_name_field ) {
19151926 const unsigned char * cp = (const unsigned char * )name ;
@@ -1935,20 +1946,32 @@ static struct cache_entry *create_from_disk(struct mem_pool *ce_mem_pool,
19351946
19361947 ce = mem_pool__ce_alloc (ce_mem_pool , len );
19371948
1938- ce -> ce_stat_data .sd_ctime .sec = get_be32 (& ondisk -> ctime .sec );
1939- ce -> ce_stat_data .sd_mtime .sec = get_be32 (& ondisk -> mtime .sec );
1940- ce -> ce_stat_data .sd_ctime .nsec = get_be32 (& ondisk -> ctime .nsec );
1941- ce -> ce_stat_data .sd_mtime .nsec = get_be32 (& ondisk -> mtime .nsec );
1942- ce -> ce_stat_data .sd_dev = get_be32 (& ondisk -> dev );
1943- ce -> ce_stat_data .sd_ino = get_be32 (& ondisk -> ino );
1944- ce -> ce_mode = get_be32 (& ondisk -> mode );
1945- ce -> ce_stat_data .sd_uid = get_be32 (& ondisk -> uid );
1946- ce -> ce_stat_data .sd_gid = get_be32 (& ondisk -> gid );
1947- ce -> ce_stat_data .sd_size = get_be32 (& ondisk -> size );
1949+ /*
1950+ * NEEDSWORK: using 'offsetof()' is cumbersome and should be replaced
1951+ * with something more akin to 'load_bitmap_entries_v1()'s use of
1952+ * 'read_be16'/'read_be32'. For consistency with the corresponding
1953+ * ondisk entry write function ('copy_cache_entry_to_ondisk()'), this
1954+ * should be done at the same time as removing references to
1955+ * 'ondisk_cache_entry' there.
1956+ */
1957+ ce -> ce_stat_data .sd_ctime .sec = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , ctime )
1958+ + offsetof(struct cache_time , sec ));
1959+ ce -> ce_stat_data .sd_mtime .sec = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , mtime )
1960+ + offsetof(struct cache_time , sec ));
1961+ ce -> ce_stat_data .sd_ctime .nsec = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , ctime )
1962+ + offsetof(struct cache_time , nsec ));
1963+ ce -> ce_stat_data .sd_mtime .nsec = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , mtime )
1964+ + offsetof(struct cache_time , nsec ));
1965+ ce -> ce_stat_data .sd_dev = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , dev ));
1966+ ce -> ce_stat_data .sd_ino = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , ino ));
1967+ ce -> ce_mode = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , mode ));
1968+ ce -> ce_stat_data .sd_uid = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , uid ));
1969+ ce -> ce_stat_data .sd_gid = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , gid ));
1970+ ce -> ce_stat_data .sd_size = get_be32 (ondisk + offsetof(struct ondisk_cache_entry , size ));
19481971 ce -> ce_flags = flags & ~CE_NAMEMASK ;
19491972 ce -> ce_namelen = len ;
19501973 ce -> index = 0 ;
1951- oidread (& ce -> oid , ondisk -> data );
1974+ oidread (& ce -> oid , ( const unsigned char * ) ondisk + offsetof( struct ondisk_cache_entry , data ) );
19521975
19531976 if (expand_name_field ) {
19541977 if (copy_len )
@@ -2117,12 +2140,12 @@ static unsigned long load_cache_entry_block(struct index_state *istate,
21172140 unsigned long src_offset = start_offset ;
21182141
21192142 for (i = offset ; i < offset + nr ; i ++ ) {
2120- struct ondisk_cache_entry * disk_ce ;
21212143 struct cache_entry * ce ;
21222144 unsigned long consumed ;
21232145
2124- disk_ce = (struct ondisk_cache_entry * )(mmap + src_offset );
2125- ce = create_from_disk (ce_mem_pool , istate -> version , disk_ce , & consumed , previous_ce );
2146+ ce = create_from_disk (ce_mem_pool , istate -> version ,
2147+ mmap + src_offset ,
2148+ & consumed , previous_ce );
21262149 set_index_entry (istate , i , ce );
21272150
21282151 src_offset += consumed ;
0 commit comments