X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fspotlight_marshalling.c;h=69733f4943676c58ec4baf7e1d20105a17d97503;hb=9b30356782a792ad0ebcf36fe4a4f276cb8e9d76;hp=47586a58892bf4e771e0691c5912361ecd28bbce;hpb=20c82671f6095de7e765a8568089460d99a2fdbf;p=netatalk.git diff --git a/etc/afpd/spotlight_marshalling.c b/etc/afpd/spotlight_marshalling.c index 47586a58..69733f49 100644 --- a/etc/afpd/spotlight_marshalling.c +++ b/etc/afpd/spotlight_marshalling.c @@ -32,8 +32,11 @@ #include #include #include +#include +#include -#include "spotlight.h" +#define MAX_SLQ_DAT (DSI_DATASIZ - 64) +#define MAX_SLQ_TOC 8192 /************************************************************************************************** * RPC data marshalling and unmarshalling @@ -64,6 +67,31 @@ /* Forward declarations */ static int sl_pack_loop(DALLOC_CTX *query, char *buf, int offset, char *toc_buf, int *toc_idx); +static int sl_unpack_loop(DALLOC_CTX *query, const char *buf, int offset, uint count, const uint toc_offset, const uint encoding); + +/************************************************************************************************** + * Wrapper functions for the *VAL macros with bound checking + **************************************************************************************************/ + +static int sivalc(char *buf, off_t off, off_t maxoff, uint32_t val) +{ + if (off + sizeof(val) >= maxoff) { + LOG(log_error, logtype_sl, "sivalc: off: %zd, maxoff: %zd", off, maxoff); + return -1; + } + SIVAL(buf, off, val); + return 0; +} + +static int slvalc(char *buf, off_t off, off_t maxoff, uint64_t val) +{ + if (off + sizeof(val) >= maxoff) { + LOG(log_error, logtype_sl, "slvalc: off: %zd, maxoff: %zd", off, maxoff); + return -1; + } + SLVAL(buf, off, val); + return 0; +} /* * Returns the UTF-16 string encoding, by checking the 2-byte byte order mark. @@ -72,21 +100,16 @@ static int sl_pack_loop(DALLOC_CTX *query, char *buf, int offset, char *toc_buf, static uint spotlight_get_utf16_string_encoding(const char *buf, int offset, int query_length, uint encoding) { uint utf16_encoding; - /* check for byte order mark */ - utf16_encoding = SL_ENC_BIG_ENDIAN; - if (query_length >= 2) { - uint16_t byte_order_mark; - if (encoding == SL_ENC_LITTLE_ENDIAN) - byte_order_mark = SVAL(buf, offset); - else - byte_order_mark = RSVAL(buf, offset); + /* Assumed encoding in absence of a bom is little endian */ + utf16_encoding = SL_ENC_LITTLE_ENDIAN; - if (byte_order_mark == 0xFFFE) { - utf16_encoding = SL_ENC_BIG_ENDIAN | SL_ENC_UTF_16; - } - else if (byte_order_mark == 0xFEFF) { + if (query_length >= 2) { + uint8_t le_bom[] = {0xff, 0xfe}; + uint8_t be_bom[] = {0xfe, 0xff}; + if (memcmp(le_bom, buf + offset, sizeof(uint16_t)) == 0) utf16_encoding = SL_ENC_LITTLE_ENDIAN | SL_ENC_UTF_16; - } + else if (memcmp(be_bom, buf + offset, sizeof(uint16_t)) == 0) + utf16_encoding = SL_ENC_BIG_ENDIAN | SL_ENC_UTF_16; } return utf16_encoding; @@ -106,142 +129,228 @@ static uint64_t sl_pack_tag(uint16_t type, uint16_t size_or_count, uint32_t val) static int sl_pack_float(double d, char *buf, int offset) { + EC_INIT; + union { double d; uint64_t w; } ieee_fp_union; - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_FLOAT, 2, 1)); - SLVAL(buf, offset + 8, ieee_fp_union.w); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_FLOAT, 2, 1)) ); + EC_ZERO( slvalc(buf, offset + 8, MAX_SLQ_DAT, ieee_fp_union.w) ); +EC_CLEANUP: + if (ret != 0) + return -1; return offset + 2 * sizeof(uint64_t); } static int sl_pack_uint64(uint64_t u, char *buf, int offset) { - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_INT64, 2, 1)); - SLVAL(buf, offset + 8, u); + EC_INIT; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_INT64, 2, 1)) ); + EC_ZERO( slvalc(buf, offset + 8, MAX_SLQ_DAT, u) ); +EC_CLEANUP: + if (ret != 0) + return -1; return offset + 2 * sizeof(uint64_t); } static int sl_pack_bool(sl_bool_t bl, char *buf, int offset) { - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_BOOL, 1, bl ? 1 : 0)); + EC_INIT; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_BOOL, 1, bl ? 1 : 0)) ); +EC_CLEANUP: + if (ret != 0) + return -1; return offset + sizeof(uint64_t); } static int sl_pack_nil(char *buf, int offset) { - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_NULL, 1, 1)); + EC_INIT; + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_NULL, 1, 1)) ); + +EC_CLEANUP: + if (ret != 0) + return -1; return offset + sizeof(uint64_t); } static int sl_pack_date(sl_time_t t, char *buf, int offset) { + EC_INIT; uint64_t data = 0; data = (t.tv_sec + SPOTLIGHT_TIME_DELTA) << 24; - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_DATE, 2, 1)); - SLVAL(buf, offset + 8, data); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_DATE, 2, 1)) ); + EC_ZERO( slvalc(buf, offset + 8, MAX_SLQ_DAT, data) ); +EC_CLEANUP: + if (ret != 0) + return -1; return offset + 2 * sizeof(uint64_t); } static int sl_pack_uuid(sl_uuid_t *uuid, char *buf, int offset) { - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_UUID, 3, 1)); + EC_INIT; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_UUID, 3, 1)) ); + if (offset + 8 + 16 >= MAX_SLQ_DAT) + EC_FAIL; memcpy(buf + offset + 8, uuid, 16); +EC_CLEANUP: + if (ret != 0) + return -1; return offset + sizeof(uint64_t) + 16; } static int sl_pack_CNID(sl_cnids_t *cnids, char *buf, int offset, char *toc_buf, int *toc_idx) { - int len = 0, off = 0; - int cnid_count = talloc_array_length(cnids->ca_cnids); + EC_INIT; + int off = 0, len; + int cnid_count = talloc_array_length(cnids->ca_cnids->dd_talloc_array); + uint64_t id; - SLVAL(toc_buf, *toc_idx * 8, sl_pack_tag(SQ_CPX_TYPE_CNIDS, (offset + SL_OFFSET_DELTA) / 8, cnid_count)); - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)); + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_CNIDS, (offset + SL_OFFSET_DELTA) / 8, 0)) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); *toc_idx += 1; offset += 8; - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_CNIDS, 2 + cnid_count, 8 /* unknown meaning, but always 8 */)); + len = cnid_count + 1; + if (cnid_count > 0) + len ++; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_CNIDS, len, 8 /* unknown meaning, but always 8 */)) ); offset += 8; if (cnid_count > 0) { - SLVAL(buf, offset, sl_pack_tag(0x0add, cnid_count, cnids->ca_context)); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(cnids->ca_unkn1, cnid_count, cnids->ca_context)) ); offset += 8; for (int i = 0; i < cnid_count; i++) { - SLVAL(buf, offset, cnids->ca_cnids->dd_talloc_array[i]); + memcpy(&id, cnids->ca_cnids->dd_talloc_array[i], sizeof(uint64_t)); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, id) ); offset += 8; } } +EC_CLEANUP: + if (ret != 0) + return -1; return offset; } static int sl_pack_array(sl_array_t *array, char *buf, int offset, char *toc_buf, int *toc_idx) { + EC_INIT; int count = talloc_array_length(array->dd_talloc_array); int octets = (offset + SL_OFFSET_DELTA) / 8; - LOG(log_maxdebug, logtype_sl, "sl_pack_array: count: %d, offset:%d, octets: %d", count, offset, octets); - - SLVAL(toc_buf, *toc_idx * 8, sl_pack_tag(SQ_CPX_TYPE_ARRAY, octets, count)); - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)); + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_ARRAY, octets, count)) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); *toc_idx += 1; offset += 8; - offset = sl_pack_loop(array, buf, offset, toc_buf, toc_idx); + EC_NEG1( offset = sl_pack_loop(array, buf, offset, toc_buf, toc_idx) ); +EC_CLEANUP: + if (ret != 0) + return -1; return offset; } static int sl_pack_dict(sl_array_t *dict, char *buf, int offset, char *toc_buf, int *toc_idx) { - SLVAL(toc_buf, *toc_idx * 8, sl_pack_tag(SQ_CPX_TYPE_DICT, (offset + SL_OFFSET_DELTA) / 8, talloc_array_length(dict->dd_talloc_array))); - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)); + EC_INIT; + + EC_ZERO( slvalc(toc_buf, + *toc_idx * 8, + MAX_SLQ_TOC, + sl_pack_tag(SQ_CPX_TYPE_DICT, + (offset + SL_OFFSET_DELTA) / 8, + talloc_array_length(dict->dd_talloc_array))) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); *toc_idx += 1; offset += 8; - offset = sl_pack_loop(dict, buf, offset, toc_buf, toc_idx); + EC_NEG1( offset = sl_pack_loop(dict, buf, offset, toc_buf, toc_idx) ); +EC_CLEANUP: + if (ret != 0) + return -1; return offset; } -static int sl_pack_string(char **string, char *buf, int offset, char *toc_buf, int *toc_idx) +static int sl_pack_filemeta(sl_filemeta_t *fm, char *buf, int offset, char *toc_buf, int *toc_idx) { + EC_INIT; + int fmlen; /* lenght of filemeta */ + int saveoff = offset; + + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); + offset += 16; + + EC_NEG1( fmlen = sl_pack(fm, buf + offset) ); + + /* Check for empty filemeta array, if it's only 40 bytes, it's only the header but no content */ + LOG(log_debug, logtype_sl, "fmlen: %d", fmlen); + if (fmlen > 40) + offset += fmlen; + else + fmlen = 0; + + EC_ZERO( slvalc(buf, saveoff + 8, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_DATA, (fmlen / 8) + 1, 8 /* unknown meaning, but always 8 */)) ); + + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_FILEMETA, (saveoff + SL_OFFSET_DELTA) / 8, fmlen / 8)) ); + *toc_idx += 1; + +EC_CLEANUP: + if (ret != 0) + return -1; + return offset; +} + +static int sl_pack_string(char *s, char *buf, int offset, char *toc_buf, int *toc_idx) +{ + EC_INIT; int len, octets, used_in_last_octet; - char *s = *string; + len = strlen(s); octets = (len / 8) + (len & 7 ? 1 : 0); used_in_last_octet = 8 - (octets * 8 - len); - LOG(log_maxdebug, logtype_sl, "sl_pack_string(\"%s\"): len: %d, octets: %d, used_in_last_octet: %d", - s, len, octets, used_in_last_octet); - - SLVAL(toc_buf, *toc_idx * 8, sl_pack_tag(SQ_CPX_TYPE_STRING, (offset + SL_OFFSET_DELTA) / 8, used_in_last_octet)); - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)); + EC_ZERO( slvalc(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, sl_pack_tag(SQ_CPX_TYPE_STRING, (offset + SL_OFFSET_DELTA) / 8, used_in_last_octet)) ); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1)) ); *toc_idx += 1; offset += 8; - SLVAL(buf, offset, sl_pack_tag(SQ_TYPE_DATA, octets + 1, used_in_last_octet)); + EC_ZERO( slvalc(buf, offset, MAX_SLQ_DAT, sl_pack_tag(SQ_TYPE_DATA, octets + 1, used_in_last_octet)) ); offset += 8; + if (offset + octets * 8 > MAX_SLQ_DAT) + EC_FAIL; memset(buf + offset, 0, octets * 8); strncpy(buf + offset, s, len); offset += octets * 8; +EC_CLEANUP: + if (ret != 0) + return -1; return offset; } static int sl_pack_loop(DALLOC_CTX *query, char *buf, int offset, char *toc_buf, int *toc_idx) { + EC_INIT; const char *type; for (int n = 0; n < talloc_array_length(query->dd_talloc_array); n++) { @@ -249,36 +358,41 @@ static int sl_pack_loop(DALLOC_CTX *query, char *buf, int offset, char *toc_buf, type = talloc_get_name(query->dd_talloc_array[n]); if (STRCMP(type, ==, "sl_array_t")) { - offset = sl_pack_array(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx); + EC_NEG1( offset = sl_pack_array(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); } else if (STRCMP(type, ==, "sl_dict_t")) { - offset = sl_pack_dict(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx); + EC_NEG1( offset = sl_pack_dict(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); + } else if (STRCMP(type, ==, "sl_filemeta_t")) { + EC_NEG1( offset = sl_pack_filemeta(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); } else if (STRCMP(type, ==, "uint64_t")) { uint64_t i; memcpy(&i, query->dd_talloc_array[n], sizeof(uint64_t)); - offset = sl_pack_uint64(i, buf, offset); + EC_NEG1( offset = sl_pack_uint64(i, buf, offset) ); } else if (STRCMP(type, ==, "char *")) { - offset = sl_pack_string(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx); + EC_NEG1( offset = sl_pack_string(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); } else if (STRCMP(type, ==, "sl_bool_t")) { sl_bool_t bl; memcpy(&bl, query->dd_talloc_array[n], sizeof(sl_bool_t)); - offset = sl_pack_bool(bl, buf, offset); + EC_NEG1( offset = sl_pack_bool(bl, buf, offset) ); } else if (STRCMP(type, ==, "double")) { double d; memcpy(&d, query->dd_talloc_array[n], sizeof(double)); - offset = sl_pack_float(d, buf, offset); + EC_NEG1( offset = sl_pack_float(d, buf, offset) ); } else if (STRCMP(type, ==, "sl_nil_t")) { - offset = sl_pack_nil(buf, offset); + EC_NEG1( offset = sl_pack_nil(buf, offset) ); } else if (STRCMP(type, ==, "sl_time_t")) { sl_time_t t; memcpy(&t, query->dd_talloc_array[n], sizeof(sl_time_t)); - offset = sl_pack_date(t, buf, offset); + EC_NEG1( offset = sl_pack_date(t, buf, offset) ); } else if (STRCMP(type, ==, "sl_uuid_t")) { - offset = sl_pack_uuid(query->dd_talloc_array[n], buf, offset); + EC_NEG1( offset = sl_pack_uuid(query->dd_talloc_array[n], buf, offset) ); } else if (STRCMP(type, ==, "sl_cnids_t")) { - offset = sl_pack_CNID(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx); + EC_NEG1( offset = sl_pack_CNID(query->dd_talloc_array[n], buf, offset, toc_buf, toc_idx) ); } } +EC_CLEANUP: + if (ret != 0) + return -1; return offset; } @@ -306,7 +420,7 @@ static int sl_unpack_ints(DALLOC_CTX *query, const char *buf, int offset, uint e i = 0; while (i++ < count) { query_data64 = sl_unpack_uint64(buf, offset, encoding); - dalloc_add(query, &query_data64, uint64_t); + dalloc_add_copy(query, &query_data64, uint64_t); offset += 8; } @@ -328,7 +442,7 @@ static int sl_unpack_date(DALLOC_CTX *query, const char *buf, int offset, uint e query_data64 = sl_unpack_uint64(buf, offset, encoding) >> 24; t.tv_sec = query_data64 - SPOTLIGHT_TIME_DELTA; t.tv_usec = 0; - dalloc_add(query, &t, sl_time_t); + dalloc_add_copy(query, &t, sl_time_t); offset += 8; } @@ -347,7 +461,7 @@ static int sl_unpack_uuid(DALLOC_CTX *query, const char *buf, int offset, uint e i = 0; while (i++ < count) { memcpy(uuid.sl_uuid, buf + offset, 16); - dalloc_add(query, &uuid, sl_uuid_t); + dalloc_add_copy(query, &uuid, sl_uuid_t); offset += 16; } @@ -387,7 +501,7 @@ static int sl_unpack_floats(DALLOC_CTX *query, const char *buf, int offset, uint ieee_fp_union.w[1] = RIVAL(buf, offset); #endif } - dalloc_add(query, &ieee_fp_union.d, double); + dalloc_add_copy(query, &ieee_fp_union.d, double); offset += 8; } @@ -399,9 +513,10 @@ static int sl_unpack_CNID(DALLOC_CTX *query, const char *buf, int offset, int le EC_INIT; int count; uint64_t query_data64; - sl_cnids_t cnids; + sl_cnids_t *cnids; - EC_NULL( cnids.ca_cnids = talloc_zero(query, DALLOC_CTX) ); + EC_NULL( cnids = talloc_zero(query, sl_cnids_t) ); + EC_NULL( cnids->ca_cnids = talloc_zero(cnids, DALLOC_CTX) ); if (length <= 16) /* that's permitted, it's an empty array */ @@ -410,18 +525,18 @@ static int sl_unpack_CNID(DALLOC_CTX *query, const char *buf, int offset, int le query_data64 = sl_unpack_uint64(buf, offset, encoding); count = query_data64 & 0xffff; - cnids.ca_unkn1 = (query_data64 & 0xffff0000) >> 16; - cnids.ca_context = query_data64 >> 32; + cnids->ca_unkn1 = (query_data64 & 0xffff0000) >> 16; + cnids->ca_context = query_data64 >> 32; offset += 8; while (count --) { query_data64 = sl_unpack_uint64(buf, offset, encoding); - dalloc_add(cnids.ca_cnids, &query_data64, uint64_t); + dalloc_add_copy(cnids->ca_cnids, &query_data64, uint64_t); offset += 8; } - dalloc_add(query, &cnids, sl_cnids_t); + dalloc_add(query, cnids, sl_cnids_t); EC_CLEANUP: EC_EXIT; @@ -469,21 +584,111 @@ static const char *spotlight_get_cpx_qtype_string(uint64_t cpx_query_type) } } -static int spotlight_dissect_loop(DALLOC_CTX *query, - const char *buf, - uint offset, - uint count, - const uint toc_offset, - const uint encoding) +static int sl_unpack_cpx(DALLOC_CTX *query, + const char *buf, + const int offset, + uint cpx_query_type, + uint cpx_query_count, + const uint toc_offset, + const uint encoding) { EC_INIT; - int i, toc_index, query_length; - uint subcount, cpx_query_type, cpx_query_count; - uint64_t query_data64, query_type; + + int roffset = offset; + uint64_t query_data64; uint unicode_encoding; uint8_t mark_exists; - char *p; - int padding, slen; + char *p, *tmp; + int qlen, used_in_last_block, slen; + sl_array_t *sl_array; + sl_dict_t *sl_dict; + sl_filemeta_t *sl_fm; + + switch (cpx_query_type) { + case SQ_CPX_TYPE_ARRAY: + sl_array = talloc_zero(query, sl_array_t); + EC_NEG1_LOG( roffset = sl_unpack_loop(sl_array, buf, offset, cpx_query_count, toc_offset, encoding) ); + dalloc_add(query, sl_array, sl_array_t); + break; + + case SQ_CPX_TYPE_DICT: + sl_dict = talloc_zero(query, sl_dict_t); + EC_NEG1_LOG( roffset = sl_unpack_loop(sl_dict, buf, offset, cpx_query_count, toc_offset, encoding) ); + dalloc_add(query, sl_dict, sl_dict_t); + break; + + case SQ_CPX_TYPE_STRING: + case SQ_CPX_TYPE_UTF16_STRING: + query_data64 = sl_unpack_uint64(buf, offset, encoding); + qlen = (query_data64 & 0xffff) * 8; + used_in_last_block = query_data64 >> 32; + slen = qlen - 16 + used_in_last_block; + + if (cpx_query_type == SQ_CPX_TYPE_STRING) { + p = dalloc_strndup(query, buf + offset + 8, slen); + } else { + unicode_encoding = spotlight_get_utf16_string_encoding(buf, offset + 8, slen, encoding); + mark_exists = (unicode_encoding & SL_ENC_UTF_16); + if (unicode_encoding & SL_ENC_BIG_ENDIAN) + EC_FAIL_LOG("Unsupported big endian UTF16 string"); + slen -= mark_exists ? 2 : 0; + EC_NEG1( convert_string_allocate(CH_UCS2, + CH_UTF8, + buf + offset + (mark_exists ? 10 : 8), + slen, + &tmp) ); + p = dalloc_strndup(query, tmp, strlen(tmp)); + free(tmp); + } + + dalloc_add(query, p, char *); + roffset += qlen; + break; + + case SQ_CPX_TYPE_FILEMETA: + query_data64 = sl_unpack_uint64(buf, offset, encoding); + qlen = (query_data64 & 0xffff) * 8; + if (qlen <= 8) { + EC_FAIL_LOG("SQ_CPX_TYPE_FILEMETA: query_length <= 8: %d", qlen); + } else { + sl_fm = talloc_zero(query, sl_filemeta_t); + EC_NEG1_LOG( sl_unpack(sl_fm, buf + offset + 8) ); + dalloc_add(query, sl_fm, sl_filemeta_t); + } + roffset += qlen; + break; + + case SQ_CPX_TYPE_CNIDS: + query_data64 = sl_unpack_uint64(buf, offset, encoding); + qlen = (query_data64 & 0xffff) * 8; + EC_NEG1_LOG( sl_unpack_CNID(query, buf, offset + 8, qlen, encoding) ); + roffset += qlen; + break; + + default: + EC_FAIL; + } + +EC_CLEANUP: + if (ret != 0) + roffset = -1; + return roffset; +} + +static int sl_unpack_loop(DALLOC_CTX *query, + const char *buf, + int offset, + uint count, + const uint toc_offset, + const uint encoding) +{ + EC_INIT; + int i, toc_index, query_length; + uint subcount; + uint64_t query_data64, query_type; + uint cpx_query_type, cpx_query_count; + sl_nil_t nil; + sl_bool_t b; while (count > 0 && (offset < toc_offset)) { query_data64 = sl_unpack_uint64(buf, offset, encoding); @@ -499,105 +704,48 @@ static int spotlight_dissect_loop(DALLOC_CTX *query, cpx_query_type = (query_data64 & 0xffff0000) >> 16; cpx_query_count = query_data64 >> 32; - switch (cpx_query_type) { - case SQ_CPX_TYPE_ARRAY: { - sl_array_t *sl_arrary = talloc_zero(query, sl_array_t); - EC_NEG1_LOG( offset = spotlight_dissect_loop(sl_arrary, buf, offset + 8, cpx_query_count, toc_offset, encoding) ); - dalloc_add(query, sl_arrary, sl_array_t); - break; - } - - case SQ_CPX_TYPE_DICT: { - sl_dict_t *sl_dict = talloc_zero(query, sl_dict_t); - EC_NEG1_LOG( offset = spotlight_dissect_loop(sl_dict, buf, offset + 8, cpx_query_count, toc_offset, encoding) ); - dalloc_add(query, sl_dict, sl_dict_t); - break; - } - case SQ_CPX_TYPE_STRING: - query_data64 = sl_unpack_uint64(buf, offset + 8, encoding); - query_length += (query_data64 & 0xffff) * 8; - if ((padding = 8 - (query_data64 >> 32)) < 0) - EC_FAIL; - if ((slen = query_length - 16 - padding) < 1) - EC_FAIL; - p = talloc_strndup(query, buf + offset + 16, slen); - dalloc_add(query, &p, char *); - break; - - case SQ_CPX_TYPE_UTF16_STRING: - query_data64 = sl_unpack_uint64(buf, offset + 8, encoding); - query_length += (query_data64 & 0xffff) * 8; - if ((padding = 8 - (query_data64 >> 32)) < 0) - EC_FAIL; - if ((slen = query_length - 16 - padding) < 1) - EC_FAIL; - - unicode_encoding = spotlight_get_utf16_string_encoding(buf, offset + 16, slen, encoding); - mark_exists = (unicode_encoding & SL_ENC_UTF_16); - unicode_encoding &= ~SL_ENC_UTF_16; - - EC_NEG1( convert_string_allocate(CH_UCS2, CH_UTF8, buf + offset + (mark_exists ? 18 : 16), slen, &p) ); - dalloc_add(query, &p, char *); - break; - - case SQ_CPX_TYPE_FILEMETA: - query_data64 = sl_unpack_uint64(buf, offset + 8, encoding); - query_length += (query_data64 & 0xffff) * 8; - - if (query_length <= 8) { - EC_FAIL_LOG("SQ_CPX_TYPE_FILEMETA: query_length <= 8%s", ""); - } else { - EC_NEG1_LOG( sl_unpack(query, buf + offset + 16) ); - } - break; - - case SQ_CPX_TYPE_CNIDS: - query_data64 = sl_unpack_uint64(buf, offset + 8, encoding); - query_length += (query_data64 & 0xffff) * 8; - EC_NEG1_LOG( sl_unpack_CNID(query, buf, offset + 16, query_length, encoding) ); - break; - } /* switch (cpx_query_type) */ - + EC_NEG1_LOG( offset = sl_unpack_cpx(query, buf, offset + 8, cpx_query_type, cpx_query_count, toc_offset, encoding)); count--; break; - - case SQ_TYPE_NULL: { + case SQ_TYPE_NULL: subcount = query_data64 >> 32; if (subcount > 64) EC_FAIL; - sl_nil_t nil = 0; + nil = 0; for (i = 0; i < subcount; i++) - dalloc_add(query, &nil, sl_nil_t); + dalloc_add_copy(query, &nil, sl_nil_t); + offset += query_length; count -= subcount; break; - } - case SQ_TYPE_BOOL: { - sl_bool_t b = query_data64 >> 32; - dalloc_add(query, &b, sl_bool_t); + case SQ_TYPE_BOOL: + b = query_data64 >> 32; + dalloc_add_copy(query, &b, sl_bool_t); + offset += query_length; count--; break; - } case SQ_TYPE_INT64: EC_NEG1_LOG( subcount = sl_unpack_ints(query, buf, offset, encoding) ); + offset += query_length; count -= subcount; break; case SQ_TYPE_UUID: EC_NEG1_LOG( subcount = sl_unpack_uuid(query, buf, offset, encoding) ); + offset += query_length; count -= subcount; break; case SQ_TYPE_FLOAT: EC_NEG1_LOG( subcount = sl_unpack_floats(query, buf, offset, encoding) ); + offset += query_length; count -= subcount; break; case SQ_TYPE_DATE: EC_NEG1_LOG( subcount = sl_unpack_date(query, buf, offset, encoding) ); + offset += query_length; count -= subcount; break; default: EC_FAIL; } - - offset += query_length; } EC_CLEANUP: @@ -611,9 +759,6 @@ EC_CLEANUP: * Global functions for packing und unpacking **************************************************************************************************/ -#define MAX_SLQ_DAT 65000 -#define MAX_SLQ_TOC 2048 - int sl_pack(DALLOC_CTX *query, char *buf) { EC_INIT; @@ -623,12 +768,13 @@ int sl_pack(DALLOC_CTX *query, char *buf) memcpy(buf, "432130dm", 8); EC_NEG1_LOG( len = sl_pack_loop(query, buf + 16, 0, toc_buf + 8, &toc_index) ); - SIVAL(buf, 8, len / 8 + 1 + toc_index + 1); - SIVAL(buf, 12, len / 8 + 1); + EC_ZERO( sivalc(buf, 8, MAX_SLQ_DAT, len / 8 + 1 + toc_index + 1) ); + EC_ZERO( sivalc(buf, 12, MAX_SLQ_DAT, len / 8 + 1) ); - SLVAL(toc_buf, 0, sl_pack_tag(SQ_TYPE_TOC, toc_index + 1, 0)); + EC_ZERO( slvalc(toc_buf, 0, MAX_SLQ_TOC, sl_pack_tag(SQ_TYPE_TOC, toc_index + 1, 0)) ); + if ((16 + len + ((toc_index + 1 ) * 8)) >= MAX_SLQ_DAT) + EC_FAIL; memcpy(buf + 16 + len, toc_buf, (toc_index + 1 ) * 8); - len += 16 + (toc_index + 1 ) * 8; EC_CLEANUP: @@ -659,7 +805,7 @@ int sl_unpack(DALLOC_CTX *query, const char *buf) toc_entries = (int)(sl_unpack_uint64(buf, toc_offset, encoding) & 0xffff); - EC_NEG1( spotlight_dissect_loop(query, buf, 0, 1, toc_offset + 8, encoding) ); + EC_NEG1( sl_unpack_loop(query, buf, 0, 1, toc_offset + 8, encoding) ); EC_CLEANUP: EC_EXIT;