38FILE_RCSID(
"@(#)$File: cdf.c,v 1.123 2022/09/24 20:30:13 christos Exp $")
56#ifdef HAVE_SYS_BSWAP_H
65#define SIZE_T_MAX CAST(size_t, ~0ULL)
71#define DPRINTF(a) printf a, fflush(stdout)
81#define NEED_SWAP (cdf_bo.u == CAST(uint32_t, 0x01020304))
84 (CAST(uint64_t, NEED_SWAP ? _cdf_tole8(x) : CAST(uint64_t, x)))
86 (CAST(uint32_t, NEED_SWAP ? _cdf_tole4(x) : CAST(uint32_t, x)))
88 (CAST(uint16_t, NEED_SWAP ? _cdf_tole2(x) : CAST(uint16_t, x)))
89#define CDF_TOLE(x) (sizeof(x) == 2 ? \
90 CDF_TOLE2(CAST(uint16_t, x)) : \
92 CDF_TOLE4(CAST(uint32_t, x)) : \
93 CDF_TOLE8(CAST(uint64_t, x))))
94#define CDF_GETUINT32(x, y) cdf_getuint32(x, y)
96#define CDF_MALLOC(n) emalloc(n)
97#define CDF_REALLOC(p, n) erealloc(p, n)
98#define CDF_CALLOC(n, u) ecalloc(n, u)
100#if defined(HAVE_BYTESWAP_H)
101# define _cdf_tole2(x) bswap_16(x)
102# define _cdf_tole4(x) bswap_32(x)
103# define _cdf_tole8(x) bswap_64(x)
104#elif defined(HAVE_SYS_BSWAP_H)
105# define _cdf_tole2(x) bswap16(x)
106# define _cdf_tole4(x) bswap32(x)
107# define _cdf_tole8(x) bswap64(x)
113_cdf_tole2(uint16_t sv)
127_cdf_tole4(uint32_t sv)
143_cdf_tole8(uint64_t sv)
165cdf_getuint32(
const uint8_t *
p,
size_t offs)
172#define CDF_UNPACK(a) \
173 (void)memcpy(&(a), &buf[len], sizeof(a)), len += sizeof(a)
174#define CDF_UNPACKA(a) \
175 (void)memcpy((a), &buf[len], sizeof(a)), len += sizeof(a)
325 const char *e =
RCAST(
const char *,
p) +
tail;
326 size_t ss = cdf_check_stream(sst, h);
328 if (e >= b &&
CAST(
size_t, e - b) <= ss * sst->
sst_len)
341 size_t siz =
CAST(
size_t, off +
len);
351 if (info->
i_fd == -1)
379 (
unsigned long long)h->
h_magic,
388 DPRINTF((
"Bad short sector size %hu\n",
449 size_t nsatpersec = (ss /
sizeof(mid)) - 1;
455#define CDF_SEC_LIMIT (UINT32_MAX / (64 * ss))
456 if ((nsatpersec > 0 &&
459 DPRINTF((
"Number of sectors in master SAT too big %u %"
490 DPRINTF((
"Reading master sector loop limit"));
495 DPRINTF((
"Reading master sector %d", mid));
498 for (k = 0; k < nsatpersec; k++, i++) {
503 DPRINTF((
"Out of bounds reading MSA %"
509 sec) !=
CAST(ssize_t, ss)) {
535 /
sizeof(maxsector));
544 for (
j = i = 0; sid >= 0; i++,
j++) {
547 DPRINTF((
"Counting chain loop limit"));
550 if (sid >= maxsector) {
551 DPRINTF((
"Sector %d >= %d\n", sid, maxsector));
557 DPRINTF((
" none, sid: %d\n", sid));
565 return CAST(
size_t, -1);
589 for (
j = i = 0; sid >= 0; i++,
j++) {
591 DPRINTF((
"Read long sector chain loop limit"));
595 DPRINTF((
"Out of bounds reading long sector chain "
601 sid)) !=
CAST(ssize_t, ss)) {
602 if (i == scn->
sst_len - 1 && nr > 0) {
606 DPRINTF((
"Reading long sector chain %d", sid));
635 for (
j = i = 0; sid >= 0; i++,
j++) {
637 DPRINTF((
"Read short sector chain loop limit"));
641 DPRINTF((
"Out of bounds reading short sector chain "
647 sid) !=
CAST(ssize_t, ss)) {
648 DPRINTF((
"Reading short sector chain %d", sid));
682 if (ns ==
CAST(
size_t, -1))
687 dir->dir_len = ns * nd;
698 for (
j = i = 0; i < ns; i++,
j++) {
700 DPRINTF((
"Read dir loop limit"));
705 DPRINTF((
"Reading directory sector %d", sid));
708 for (
j = 0;
j < nd;
j++) {
715 for (i = 0; i <
dir->dir_len; i++)
744 for (
j = i = 0; sid >= 0; i++,
j++) {
746 DPRINTF((
"Read short sat sector loop limit"));
750 DPRINTF((
"Out of bounds reading short sector chain "
757 DPRINTF((
"Reading short sat sector %d", sid));
779 for (i = 0; i <
dir->dir_len; i++)
784 if (i ==
dir->dir_len) {
785 DPRINTF((
"Cannot find root storage dir\n"));
788 d = &
dir->dir_tab[i];
793 DPRINTF((
"No first secror in dir\n"));
806cdf_namecmp(
const char *d,
const uint16_t *
s,
size_t l)
808 for (; l--; d++,
s++)
820 "\05DocumentSummaryInformation", scn);
829 "\05SummaryInformation", scn);
841 memset(scn, 0,
sizeof(*scn));
845 d = &
dir->dir_tab[i - 1];
855 for (i =
dir->dir_len; i > 0; i--)
856 if (
dir->dir_tab[i - 1].d_type ==
type &&
857 cdf_namecmp(
name,
dir->dir_tab[i - 1].d_name, name_len)
868#define CDF_SHLEN_LIMIT (UINT32_MAX / 64)
869#define CDF_PROP_LIMIT (UINT32_MAX / (64 * sizeof(cdf_property_info_t)))
872cdf_offset(
const void *
p,
size_t l)
874 return CAST(
const void *,
CAST(
const uint8_t *,
p) + l);
877static const uint8_t *
879 const uint8_t *
p,
const uint8_t *e,
size_t i)
881 size_t tail = (i << 1) + 1;
885 DPRINTF((
"Past end %p < %p\n", e,
p));
889 if (cdf_check_stream_offset(sst, h,
p, (
tail + 1) *
sizeof(uint32_t),
894 if (ofs < 2 *
sizeof(uint32_t)) {
895 DPRINTF((
"Offset too small %zu\n", ofs));
899 ofs -= 2 *
sizeof(uint32_t);
900 if (ofs >
CAST(
size_t, e -
p)) {
901 DPRINTF((
"Offset too big %zu %td\n", ofs, e -
p));
905 return CAST(
const uint8_t *, cdf_offset(
CAST(
const void *,
p), ofs));
912 size_t newcount = *maxcount + incr;
925 *maxcount = newcount;
968 const uint8_t *
p, *q, *e;
969 size_t i, o4, nelements,
j, slen,
left;
977 cdf_offset(sst->
sst_tab, offs));
978 if (cdf_check_stream_offset(sst, h, shp,
sizeof(*shp), __LINE__) == -1)
986 if (cdf_check_stream_offset(sst, h, shp, sh.
sh_len, __LINE__) == -1)
999 p =
CAST(
const uint8_t *, cdf_offset(sst->
sst_tab, offs +
sizeof(sh)));
1000 e =
CAST(
const uint8_t *, cdf_offset(shp, sh.
sh_len));
1001 if (
p >= e || cdf_check_stream_offset(sst, h, e, 0, __LINE__) == -1)
1005 if ((q = cdf_get_property_info_pos(sst, h,
p, e, i)) ==
NULL)
1009 if (
left <
sizeof(uint32_t)) {
1010 DPRINTF((
"short info (no type)_\n"));
1015 i, inp[i].pi_id, inp[i].pi_type, q -
p, offs));
1017 if (
left <
sizeof(uint32_t) * 2) {
1018 DPRINTF((
"missing CDF_VECTOR length\n"));
1023 DPRINTF((
"CDF_VECTOR with nelements == %"
1032 o4 = slen *
sizeof(uint32_t);
1040 if (!cdf_copy_info(&inp[i], &q[o4], e,
sizeof(int16_t)))
1047 if (!cdf_copy_info(&inp[i], &q[o4], e,
sizeof(int32_t)))
1054 if (!cdf_copy_info(&inp[i], &q[o4], e,
sizeof(int64_t)))
1059 if (nelements > 1) {
1060 size_t nelem = inp - *info;
1061 inp = cdf_grow_info(info, maxcount, nelements);
1071 if (o4 +
sizeof(uint32_t) >
left)
1075 o4 +=
sizeof(uint32_t);
1079 inp[i].pi_str.
s_len = l;
1080 inp[i].pi_str.
s_buf =
CAST(
const char *,
1081 CAST(
const void *, &q[o4]));
1085 "u s=%.*s\n", o4, l,
1093 o4 = slen *
sizeof(uint32_t);
1103 memset(&inp[i].pi_val, 0,
sizeof(inp[i].pi_val));
1104 DPRINTF((
"Don't know how to deal with %#x\n",
1131 if (cdf_check_stream_offset(sst, h, si,
sizeof(*si), __LINE__) == -1 ||
1132 cdf_check_stream_offset(sst, h, sd,
sizeof(*sd), __LINE__) == -1)
1144 count, &maxcount) == -1)
1150#define extract_catalog_field(t, f, l) \
1151 if (b + l + sizeof(cep->f) > eb) { \
1152 cep->ce_namlen = 0; \
1155 memcpy(&cep->f, b + (l), sizeof(cep->f)); \
1156 ce[i].f = CAST(t, CDF_TOLE(cep->f))
1162 size_t ss = cdf_check_stream(sst, h);
1164 const char *nb, *eb = b + ss * sst->
sst_len;
1170 for (nr = 0;; nr++) {
1171 memcpy(&reclen, b,
sizeof(reclen));
1187 memset(ce, 0, nr *
sizeof(*ce));
1189 for (
j = i = 0; i < nr; b += reclen) {
1208 np =
CAST(
const uint16_t *,
CAST(
const void *, (b + 16)));
1209 nb =
CAST(
const char *,
CAST(
const void *,
1222 (*cat)->cat_num =
j;
1229 return snprintf(
buf, buflen,
"%.8x-%.4x-%.4x-%.2x%.2x-"
1236static const struct {
1277 int days, hours, mins, secs;
1280 secs =
CAST(
int, ts % 60);
1282 mins =
CAST(
int, ts % 60);
1284 hours =
CAST(
int, ts % 24);
1286 days =
CAST(
int, ts);
1290 if (
CAST(
size_t,
len) >= bufsiz)
1294 if (days || hours) {
1296 if (
CAST(
size_t,
len) >= bufsiz)
1301 if (
CAST(
size_t,
len) >= bufsiz)
1312 for (i = 0; i <
len &&
p[i]; i++)
1324#define DUMP(a, b) (void)fprintf(stderr, "%40.40s = " a "\n", # b, h->h_ ## b)
1325#define DUMP2(a, b) (void)fprintf(stderr, "%40.40s = " a " (" a ")\n", # b, \
1326 h->h_ ## b, 1 << h->h_ ## b)
1327 DUMP(
"%d", revision);
1328 DUMP(
"%d", version);
1329 DUMP(
"%#x", byte_order);
1330 DUMP2(
"%d", sec_size_p2);
1331 DUMP2(
"%d", short_sec_size_p2);
1332 DUMP(
"%d", num_sectors_in_sat);
1333 DUMP(
"%d", secid_first_directory);
1334 DUMP(
"%d", min_size_standard_stream);
1335 DUMP(
"%d", secid_first_sector_in_short_sat);
1336 DUMP(
"%d", num_sectors_in_short_sat);
1337 DUMP(
"%d", secid_first_sector_in_master_sat);
1338 DUMP(
"%d", num_sectors_in_master_sat);
1352 for (i = 0; i < sat->
sat_len; i++) {
1355 for (
j = 0;
j <
s;
j++) {
1358 if ((
j + 1) % 10 == 0)
1360 "u: ", i *
s +
j + 1);
1367cdf_dump(
const void *
v,
size_t len)
1370 const unsigned char *
p =
v;
1374 for (i = 0,
j = 0; i <
len; i++,
p++) {
1376 abuf[
j++] = isprint(*
p) ? *
p :
'.';
1405 static const char *
types[] = {
"empty",
"user storage",
1406 "user stream",
"lockbytes",
"property",
"root storage" };
1408 for (i = 0; i <
dir->dir_len; i++) {
1410 d = &
dir->dir_tab[i];
1411 for (
j = 0;
j <
sizeof(
name);
j++)
1420 d->
d_color ?
"black" :
"red");
1440 warn(
"Can't read stream for %s at %d len %d",
1444 cdf_dump_stream(&scn);
1462 for (i = 0; i <
count; i++) {
1465 switch (info[i].pi_type) {
1491 info[i].pi_str.s_len, info[i].pi_str.s_buf);
1496 for (
j = 0;
j < info[i].pi_str.
s_len - 1;
j++)
1497 (
void)fputc(info[i].
pi_str.s_buf[
j << 1], stderr);
1502 if (tp < 1000000000000000LL) {
1516 DPRINTF((
"Don't know how to deal with %#x\n",
1542 cdf_dump_property_info(info,
count);
1554 char tbuf[64], sbuf[256];
1558 for (i = 0; i < cat->
cat_num; i++) {
1560 printf(
"\t%d %s %s", ce[i].ce_num,
1561 cdf_u16tos8(sbuf, ce[i].ce_namlen, ce[i].ce_name),
1571main(
int argc,
char *argv[])
1581#define getprogname() __progname
1582 extern char *__progname;
1585 (
void)
fprintf(stderr,
"Usage: %s <filename>\n", getprogname());
1591 for (i = 1; i < argc; i++) {
1592 if ((info.
i_fd = open(argv[1], O_RDONLY)) == -1)
1593 err(EXIT_FAILURE,
"Cannot open `%s'", argv[1]);
1596 err(EXIT_FAILURE,
"Cannot read header");
1598 cdf_dump_header(&h);
1602 err(EXIT_FAILURE,
"Cannot read sat");
1608 err(EXIT_FAILURE,
"Cannot read ssat");
1614 err(EXIT_FAILURE,
"Cannot read dir");
1618 err(EXIT_FAILURE,
"Cannot read short stream");
1620 cdf_dump_stream(&sst);
1624 cdf_dump_dir(&info, &h, &sat, &ssat, &sst, &
dir);
1630 warn(
"Cannot read summary info");
1633 cdf_dump_summary_info(&h, &scn);
1636 &
dir,
"Catalog", &scn) == -1)
1637 warn(
"Cannot read catalog");
1640 cdf_dump_catalog(&h, &scn);
fprintf($stream, string $format, mixed ... $values)
printf(string $format, mixed ... $values)
dir(string $directory, $context=null)
count(Countable|array $value, int $mode=COUNT_NORMAL)
assert(mixed $assertion, Throwable|string|null $description=null)
int cdf_print_property_name(char *buf, size_t bufsiz, uint32_t p)
int cdf_zero_stream(cdf_stream_t *scn)
int cdf_unpack_catalog(const cdf_header_t *h, const cdf_stream_t *sst, cdf_catalog_t **cat)
void cdf_swap_dir(cdf_directory_t *d)
char * cdf_u16tos8(char *buf, size_t len, const uint16_t *p)
uint64_t cdf_tole8(uint64_t sv)
int cdf_read_summary_info(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn)
void cdf_swap_header(cdf_header_t *h)
int cdf_read_doc_summary_info(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, const cdf_dir_t *dir, cdf_stream_t *scn)
int cdf_find_stream(const cdf_dir_t *dir, const char *name, int type)
void cdf_swap_class(cdf_classid_t *d)
int cdf_read_long_sector_chain(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, cdf_secid_t sid, size_t len, cdf_stream_t *scn)
int cdf_read_dir(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, cdf_dir_t *dir)
int cdf_read_short_stream(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_dir_t *dir, cdf_stream_t *scn, const cdf_directory_t **root)
ssize_t cdf_read_short_sector(const cdf_stream_t *sst, void *buf, size_t offs, size_t len, const cdf_header_t *h, cdf_secid_t id)
int cdf_read_user_stream(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, const cdf_dir_t *dir, const char *name, cdf_stream_t *scn)
int cdf_read_ssat(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, cdf_sat_t *ssat)
#define CDF_REALLOC(p, n)
void cdf_unpack_header(cdf_header_t *h, char *buf)
int cdf_unpack_summary_info(const cdf_stream_t *sst, const cdf_header_t *h, cdf_summary_info_header_t *ssi, cdf_property_info_t **info, size_t *count)
size_t cdf_count_chain(const cdf_sat_t *sat, cdf_secid_t sid, size_t size)
int cdf_read_short_sector_chain(const cdf_header_t *h, const cdf_sat_t *ssat, const cdf_stream_t *sst, cdf_secid_t sid, size_t len, cdf_stream_t *scn)
int cdf_read_sector_chain(const cdf_info_t *info, const cdf_header_t *h, const cdf_sat_t *sat, const cdf_sat_t *ssat, const cdf_stream_t *sst, cdf_secid_t sid, size_t len, cdf_stream_t *scn)
int cdf_print_elapsed_time(char *buf, size_t bufsiz, cdf_timestamp_t ts)
ssize_t cdf_read_sector(const cdf_info_t *info, void *buf, size_t offs, size_t len, const cdf_header_t *h, cdf_secid_t id)
#define extract_catalog_field(t, f, l)
int cdf_read_header(const cdf_info_t *info, cdf_header_t *h)
#define CDF_GETUINT32(x, y)
uint16_t cdf_tole2(uint16_t sv)
int cdf_read_property_info(const cdf_stream_t *sst, const cdf_header_t *h, uint32_t offs, cdf_property_info_t **info, size_t *count, size_t *maxcount)
int cdf_print_classid(char *buf, size_t buflen, const cdf_classid_t *id)
uint32_t cdf_tole4(uint32_t sv)
void cdf_unpack_dir(cdf_directory_t *d, char *buf)
int cdf_read_sat(const cdf_info_t *info, cdf_header_t *h, cdf_sat_t *sat)
#define CDF_ROUND(val, by)
#define CDF_SEC_POS(h, secid)
#define CDF_PROPERTY_LOCALE_ID
#define CDF_SECTION_DECLARATION_OFFSET
#define CDF_DIR_TYPE_USER_STREAM
#define CDF_PROPERTY_AUTHOR
#define CDF_PROPERTY_CREATE_TIME
#define CDF_PROPERTY_LAST_SAVED_TIME
#define CDF_PROPERTY_LAST_PRINTED
#define CDF_ELEMENT_LIMIT
#define CDF_SHORT_SEC_POS(h, secid)
#define CDF_PROPERTY_NUMBER_OF_PAGES
int cdf_timestamp_to_timespec(struct timespec *, cdf_timestamp_t)
#define CDF_PROPERTY_TITLE
#define CDF_PROPERTY_COMMENTS
#define CDF_DIR_TYPE_USER_STORAGE
#define CDF_PROPERTY_SUBJECT
#define CDF_DIR_TYPE_ROOT_STORAGE
#define CDF_PROPERTY_KEYWORDS
#define CDF_PROPERTY_CODE_PAGE
#define CDF_PROPERTY_NAME_OF_APPLICATION
#define CDF_PROPERTY_SECURITY
#define CDF_DIRECTORY_SIZE
#define CDF_PROPERTY_NUMBER_OF_CHARACTERS
#define CDF_PROPERTY_TOTAL_EDITING_TIME
#define CDF_PROPERTY_LAST_SAVED_BY
#define CDF_PROPERTY_TEMPLATE
#define CDF_LENGTH32_STRING
#define CDF_PROPERTY_THUMBNAIL
char * cdf_ctime(const time_t *, char *)
#define CDF_SECID_END_OF_CHAIN
#define CDF_SHORT_SEC_SIZE(h)
#define CDF_PROPERTY_NUMBER_OF_WORDS
#define CDF_LENGTH32_WSTRING
#define CDF_PROPERTY_REVISION_NUMBER
memset(ptr, 0, type->size)
zend_ffi_ctype_name_buf buf
unsigned const char * pos
struct php_pcntl_pending_signal * tail
cdf_catalog_entry_t cat_e[1]
cdf_timestamp_t d_created
cdf_secid_t d_stream_first_sector
cdf_timestamp_t d_modified
cdf_dirid_t d_right_child
uint64_t d_storage_uuid[2]
const unsigned char * i_buf
union cdf_property_info_t::@075346152224251060231334060340141304330336174004 pi_val
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)