LCOV - code coverage report
Current view: top level - source3/rpc_server/mdssvc - marshalling.c (source / functions) Hit Total Coverage
Test: coverage report for master 70ed9daf Lines: 497 741 67.1 %
Date: 2024-01-11 09:59:51 Functions: 27 29 93.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Main metadata server / Spotlight routines
       4             : 
       5             :    Copyright (C) Ralph Boehme                   2012-2014
       6             : 
       7             :    This program is free software; you can redistribute it and/or modify
       8             :    it under the terms of the GNU General Public License as published by
       9             :    the Free Software Foundation; either version 3 of the License, or
      10             :    (at your option) any later version.
      11             : 
      12             :    This program is distributed in the hope that it will be useful,
      13             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :    GNU General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU General Public License
      18             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include "includes.h"
      22             : #include "dalloc.h"
      23             : #include "marshalling.h"
      24             : 
      25             : #undef DBGC_CLASS
      26             : #define DBGC_CLASS DBGC_RPC_SRV
      27             : 
      28             : /*
      29             :  * This is used to talloc an array that will hold the table of
      30             :  * contents of a marshalled Spotlight RPC (S-RPC) reply. Each ToC
      31             :  * entry is 8 bytes, so we allocate space for 1024 entries which
      32             :  * should be sufficient for even the largest S-RPC replies.
      33             :  *
      34             :  * The total buffersize for S-RPC packets is typically limited to 64k,
      35             :  * so we can only store so many elements there anyway.
      36             :  */
      37             : #define MAX_SLQ_TOC 1024*64
      38             : #define MAX_SLQ_TOCIDX 1024*8
      39             : #define MAX_SLQ_COUNT 1024*64
      40             : #define MAX_SL_STRLEN 1024
      41             : 
      42             : /******************************************************************************
      43             :  * RPC data marshalling and unmarshalling
      44             :  ******************************************************************************/
      45             : 
      46             : /* Spotlight epoch is 1.1.2001 00:00 UTC */
      47             : #define SPOTLIGHT_TIME_DELTA 978307200 /* Diff from UNIX epoch to Spotlight epoch */
      48             : 
      49             : #define SQ_TYPE_NULL    0x0000
      50             : #define SQ_TYPE_COMPLEX 0x0200
      51             : #define SQ_TYPE_INT64   0x8400
      52             : #define SQ_TYPE_BOOL    0x0100
      53             : #define SQ_TYPE_FLOAT   0x8500
      54             : #define SQ_TYPE_DATA    0x0700
      55             : #define SQ_TYPE_CNIDS   0x8700
      56             : #define SQ_TYPE_UUID    0x0e00
      57             : #define SQ_TYPE_DATE    0x8600
      58             : #define SQ_TYPE_TOC     0x8800
      59             : 
      60             : #define SQ_CPX_TYPE_ARRAY           0x0a00
      61             : #define SQ_CPX_TYPE_STRING          0x0c00
      62             : #define SQ_CPX_TYPE_UTF16_STRING    0x1c00
      63             : #define SQ_CPX_TYPE_DICT            0x0d00
      64             : #define SQ_CPX_TYPE_CNIDS           0x1a00
      65             : #define SQ_CPX_TYPE_FILEMETA        0x1b00
      66             : 
      67             : struct sl_tag  {
      68             :         int type;
      69             :         int count;
      70             :         size_t length;
      71             :         size_t size;
      72             : };
      73             : 
      74             : static ssize_t sl_pack_loop(DALLOC_CTX *query, char *buf,
      75             :                             ssize_t offset, size_t bufsize,
      76             :                             char *toc_buf, int *toc_idx, int *count);
      77             : static ssize_t sl_unpack_loop(DALLOC_CTX *query, const char *buf,
      78             :                               ssize_t offset, size_t bufsize,
      79             :                               int count, ssize_t toc_offset,
      80             :                               int encoding);
      81             : static ssize_t sl_pack(DALLOC_CTX *query, char *buf, size_t bufsize);
      82             : 
      83             : /******************************************************************************
      84             :  * Wrapper functions for the *VAL macros with bound checking
      85             :  ******************************************************************************/
      86             : 
      87        1684 : static ssize_t sl_push_uint64_val(char *buf,
      88             :                                   ssize_t offset,
      89             :                                   size_t max_offset,
      90             :                                   uint64_t val)
      91             : {
      92        1684 :         if (offset + 8 > max_offset) {
      93           0 :                 DEBUG(1, ("%s: offset: %zd, max_offset: %zu\n",
      94             :                           __func__, offset, max_offset));
      95           0 :                 return -1;
      96             :         }
      97             : 
      98        1684 :         SBVAL(buf, offset, val);
      99        1684 :         return offset + 8;
     100             : }
     101             : 
     102         326 : static ssize_t sl_pull_uint64_val(const char *buf,
     103             :                                   ssize_t offset,
     104             :                                   size_t bufsize,
     105             :                                   uint encoding,
     106             :                                   uint64_t *presult)
     107             : {
     108           2 :         uint64_t val;
     109             : 
     110         326 :         if (offset + 8 > bufsize) {
     111           0 :                 DEBUG(1,("%s: buffer overflow\n", __func__));
     112           0 :                 return -1;
     113             :         }
     114             : 
     115         326 :         if (encoding == SL_ENC_LITTLE_ENDIAN) {
     116         326 :                 val = BVAL(buf, offset);
     117             :         } else {
     118           0 :                 val = RBVAL(buf, offset);
     119             :         }
     120             : 
     121         326 :         *presult = val;
     122             : 
     123         326 :         return offset + 8;
     124             : }
     125             : 
     126             : /*
     127             :  * Returns the UTF-16 string encoding, by checking the 2-byte byte order mark.
     128             :  * If there is no byte order mark, -1 is returned.
     129             :  */
     130          10 : static int spotlight_get_utf16_string_encoding(const char *buf, ssize_t offset,
     131             :                                                size_t query_length, int encoding)
     132             : {
     133           0 :         int utf16_encoding;
     134             : 
     135             :         /* Assumed encoding in absence of a bom is little endian */
     136          10 :         utf16_encoding = SL_ENC_LITTLE_ENDIAN;
     137             : 
     138          10 :         if (query_length >= 2) {
     139          10 :                 uint8_t le_bom[] = {0xff, 0xfe};
     140          10 :                 uint8_t be_bom[] = {0xfe, 0xff};
     141          10 :                 if (memcmp(le_bom, buf + offset, sizeof(uint16_t)) == 0) {
     142          10 :                         utf16_encoding = SL_ENC_LITTLE_ENDIAN | SL_ENC_UTF_16;
     143           0 :                 } else if (memcmp(be_bom, buf + offset, sizeof(uint16_t)) == 0) {
     144           0 :                         utf16_encoding = SL_ENC_BIG_ENDIAN | SL_ENC_UTF_16;
     145             :                 }
     146             :         }
     147             : 
     148          10 :         return utf16_encoding;
     149             : }
     150             : 
     151             : /******************************************************************************
     152             :  * marshalling functions
     153             :  ******************************************************************************/
     154             : 
     155        1392 : static inline uint64_t sl_pack_tag(uint16_t type, uint16_t size_or_count, uint32_t val)
     156             : {
     157        1392 :         uint64_t tag = ((uint64_t)val << 32) | ((uint64_t)type << 16) | size_or_count;
     158        1392 :         return tag;
     159             : }
     160             : 
     161           6 : static ssize_t sl_pack_float(double d, char *buf, ssize_t offset, size_t bufsize)
     162             : {
     163           0 :         union {
     164             :                 double d;
     165             :                 uint64_t w;
     166             :         } ieee_fp_union;
     167             : 
     168           6 :         ieee_fp_union.d = d;
     169             : 
     170           6 :         offset = sl_push_uint64_val(buf, offset, bufsize, sl_pack_tag(SQ_TYPE_FLOAT, 2, 1));
     171           6 :         if (offset == -1) {
     172           0 :                 return -1;
     173             :         }
     174           6 :         offset = sl_push_uint64_val(buf, offset, bufsize, ieee_fp_union.w);
     175           6 :         if (offset == -1) {
     176           0 :                 return -1;
     177             :         }
     178             : 
     179           6 :         return offset;
     180             : }
     181             : 
     182          44 : static ssize_t sl_pack_uint64(uint64_t u, char *buf, ssize_t offset, size_t bufsize)
     183             : {
     184           0 :         uint64_t tag;
     185             : 
     186          44 :         tag = sl_pack_tag(SQ_TYPE_INT64, 2, 1);
     187          44 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     188          44 :         if (offset == -1) {
     189           0 :                 return -1;
     190             :         }
     191          44 :         offset = sl_push_uint64_val(buf, offset, bufsize, u);
     192          44 :         if (offset == -1) {
     193           0 :                 return -1;
     194             :         }
     195             : 
     196          44 :         return offset;
     197             : }
     198             : 
     199          58 : static ssize_t sl_pack_uint64_array(uint64_t *u, char *buf, ssize_t offset, size_t bufsize, int *toc_count)
     200             : {
     201           0 :         int count, i;
     202           0 :         uint64_t tag;
     203             : 
     204          58 :         count = talloc_array_length(u);
     205             : 
     206          58 :         tag = sl_pack_tag(SQ_TYPE_INT64, count + 1, count);
     207          58 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     208          58 :         if (offset == -1) {
     209           0 :                 return -1;
     210             :         }
     211             : 
     212         174 :         for (i = 0; i < count; i++) {
     213         116 :                 offset = sl_push_uint64_val(buf, offset, bufsize, u[i]);
     214         116 :                 if (offset == -1) {
     215           0 :                         return -1;
     216             :                 }
     217             :         }
     218             : 
     219          58 :         if (count > 1) {
     220          58 :                 *toc_count += (count - 1);
     221             :         }
     222             : 
     223          58 :         return offset;
     224             : }
     225             : 
     226           8 : static ssize_t sl_pack_bool(sl_bool_t val, char *buf, ssize_t offset, size_t bufsize)
     227             : {
     228           0 :         uint64_t tag;
     229             : 
     230           8 :         tag = sl_pack_tag(SQ_TYPE_BOOL, 1, val ? 1 : 0);
     231           8 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     232           8 :         if (offset == -1) {
     233           0 :                 return -1;
     234             :         }
     235             : 
     236           8 :         return offset;
     237             : }
     238             : 
     239          10 : static ssize_t sl_pack_nil(char *buf, ssize_t offset, size_t bufsize)
     240             : {
     241           0 :         uint64_t tag;
     242             : 
     243          10 :         tag = sl_pack_tag(SQ_TYPE_NULL, 1, 1);
     244          10 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     245          10 :         if (offset == -1) {
     246           0 :                 return -1;
     247             :         }
     248             : 
     249          10 :         return offset;
     250             : }
     251             : 
     252           0 : static ssize_t sl_pack_date(sl_time_t t, char *buf, ssize_t offset, size_t bufsize)
     253             : {
     254           0 :         uint64_t data;
     255           0 :         uint64_t tag;
     256           0 :         union {
     257             :                 double d;
     258             :                 uint64_t w;
     259             :         } ieee_fp_union;
     260             : 
     261           0 :         tag = sl_pack_tag(SQ_TYPE_DATE, 2, 1);
     262           0 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     263           0 :         if (offset == -1) {
     264           0 :                 return -1;
     265             :         }
     266             : 
     267           0 :         ieee_fp_union.d = (double)(t.tv_sec - SPOTLIGHT_TIME_DELTA);
     268           0 :         ieee_fp_union.d += (double)t.tv_usec / 1000000;
     269             : 
     270           0 :         data = ieee_fp_union.w;
     271           0 :         offset = sl_push_uint64_val(buf, offset, bufsize, data);
     272           0 :         if (offset == -1) {
     273           0 :                 return -1;
     274             :         }
     275             : 
     276           0 :         return offset;
     277             : }
     278             : 
     279           4 : static ssize_t sl_pack_uuid(sl_uuid_t *uuid, char *buf, ssize_t offset, size_t bufsize)
     280             : {
     281           0 :         uint64_t tag;
     282             : 
     283           4 :         tag = sl_pack_tag(SQ_TYPE_UUID, 3, 1);
     284           4 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     285           4 :         if (offset == -1) {
     286           0 :                 return -1;
     287             :         }
     288             : 
     289           4 :         if (offset + 16 > bufsize) {
     290           0 :                 return -1;
     291             :         }
     292           4 :         memcpy(buf + offset, uuid, 16);
     293             : 
     294           4 :         return offset + 16;
     295             : }
     296             : 
     297          38 : static ssize_t sl_pack_CNID(sl_cnids_t *cnids, char *buf, ssize_t offset,
     298             :                             size_t bufsize, char *toc_buf, int *toc_idx)
     299             : {
     300           0 :         ssize_t result;
     301           0 :         int len, i;
     302          38 :         int cnid_count = dalloc_size(cnids->ca_cnids);
     303           0 :         uint64_t tag;
     304           0 :         uint64_t id;
     305           0 :         void *p;
     306             : 
     307          38 :         tag = sl_pack_tag(SQ_CPX_TYPE_CNIDS, offset / 8, 0);
     308          38 :         result = sl_push_uint64_val(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, tag);
     309          38 :         if (result == -1) {
     310           0 :                 return -1;
     311             :         }
     312             : 
     313          38 :         tag = sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1);
     314          38 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     315          38 :         if (offset == -1) {
     316           0 :                 return -1;
     317             :         }
     318             : 
     319          38 :         *toc_idx += 1;
     320             : 
     321          38 :         len = cnid_count + 1;
     322          38 :         if (cnid_count > 0) {
     323          36 :                 len ++;
     324             :         }
     325             : 
     326             :         /* unknown meaning, but always 8 */
     327          38 :         tag = sl_pack_tag(SQ_TYPE_CNIDS, len, 8 );
     328          38 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     329          38 :         if (offset == -1) {
     330           0 :                 return -1;
     331             :         }
     332             : 
     333          38 :         if (cnid_count > 0) {
     334          36 :                 tag = sl_pack_tag(cnids->ca_unkn1, cnid_count, cnids->ca_context);
     335          36 :                 offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     336          36 :                 if (offset == -1) {
     337           0 :                         return -1;
     338             :                 }
     339             : 
     340          74 :                 for (i = 0; i < cnid_count; i++) {
     341          38 :                         p = dalloc_get_object(cnids->ca_cnids, i);
     342          38 :                         if (p == NULL) {
     343           0 :                                 return -1;
     344             :                         }
     345          38 :                         memcpy(&id, p, sizeof(uint64_t));
     346          38 :                         offset = sl_push_uint64_val(buf, offset, bufsize, id);
     347          38 :                         if (offset == -1) {
     348           0 :                                 return -1;
     349             :                         }
     350             :                 }
     351             :         }
     352             : 
     353          38 :         return offset;
     354             : }
     355             : 
     356         196 : static ssize_t sl_pack_array(sl_array_t *array, char *buf, ssize_t offset,
     357             :                              size_t bufsize, char *toc_buf, int *toc_idx)
     358             : {
     359           0 :         ssize_t result;
     360         196 :         int count = dalloc_size(array);
     361         196 :         int octets = offset / 8;
     362           0 :         uint64_t tag;
     363         196 :         int toc_idx_save = *toc_idx;
     364             : 
     365         196 :         tag = sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1);
     366         196 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     367         196 :         if (offset == -1) {
     368           0 :                 return -1;
     369             :         }
     370             : 
     371         196 :         *toc_idx += 1;
     372             : 
     373         196 :         offset = sl_pack_loop(array, buf, offset, bufsize - offset, toc_buf, toc_idx, &count);
     374             : 
     375         196 :         tag = sl_pack_tag(SQ_CPX_TYPE_ARRAY, octets, count);
     376         196 :         result = sl_push_uint64_val(toc_buf, toc_idx_save * 8, MAX_SLQ_TOC, tag);
     377         196 :         if (result == -1) {
     378           0 :                 return -1;
     379             :         }
     380             : 
     381         196 :         return offset;
     382             : }
     383             : 
     384          10 : static ssize_t sl_pack_dict(sl_array_t *dict, char *buf, ssize_t offset,
     385             :                             size_t bufsize, char *toc_buf, int *toc_idx, int *count)
     386             : {
     387           0 :         ssize_t result;
     388           0 :         uint64_t tag;
     389             : 
     390          10 :         tag = sl_pack_tag(SQ_CPX_TYPE_DICT, offset / 8,
     391          10 :                           dalloc_size(dict));
     392          10 :         result = sl_push_uint64_val(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, tag);
     393          10 :         if (result == -1) {
     394           0 :                 return -1;
     395             :         }
     396             : 
     397          10 :         tag = sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1);
     398          10 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     399          10 :         if (offset == -1) {
     400           0 :                 return -1;
     401             :         }
     402             : 
     403          10 :         *toc_idx += 1;
     404             : 
     405          10 :         offset = sl_pack_loop(dict, buf, offset, bufsize - offset, toc_buf, toc_idx, count);
     406             : 
     407          10 :         return offset;
     408             : }
     409             : 
     410          10 : static ssize_t sl_pack_filemeta(sl_filemeta_t *fm, char *buf, ssize_t offset,
     411             :                                 size_t bufsize, char *toc_buf, int *toc_idx)
     412             : {
     413           0 :         ssize_t result;
     414           0 :         ssize_t fmlen;
     415          10 :         ssize_t saveoff = offset;
     416           0 :         uint64_t tag;
     417             : 
     418          10 :         tag = sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1);
     419          10 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     420          10 :         if (offset == -1) {
     421           0 :                 return -1;
     422             :         }
     423             : 
     424          10 :         offset += 8;
     425             : 
     426          10 :         fmlen = sl_pack(fm, buf + offset, bufsize - offset);
     427          10 :         if (fmlen == -1) {
     428           0 :                 return -1;
     429             :         }
     430             : 
     431             :         /*
     432             :          * Check for empty filemeta array, if it's only 40 bytes, it's
     433             :          * only the header but no content
     434             :          */
     435          10 :         if (fmlen > 40) {
     436           8 :                 offset += fmlen;
     437             :         } else {
     438           2 :                 fmlen = 0;
     439             :         }
     440             : 
     441             :         /* unknown meaning, but always 8 */
     442          10 :         tag = sl_pack_tag(SQ_TYPE_DATA, (fmlen / 8) + 1, 8);
     443          10 :         result = sl_push_uint64_val(buf, saveoff + 8, bufsize, tag);
     444          10 :         if (result == -1) {
     445           0 :                 return -1;
     446             :         }
     447             : 
     448          10 :         tag = sl_pack_tag(SQ_CPX_TYPE_FILEMETA, saveoff / 8, fmlen / 8);
     449          10 :         result = sl_push_uint64_val(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, tag);
     450          10 :         if (result == -1) {
     451           0 :                 return -1;
     452             :         }
     453             : 
     454          10 :         *toc_idx += 1;
     455             : 
     456          10 :         return offset;
     457             : }
     458             : 
     459         192 : static ssize_t sl_pack_string(char *s, char *buf, ssize_t offset, size_t bufsize,
     460             :                               char *toc_buf, int *toc_idx)
     461             : {
     462           0 :         ssize_t result;
     463           0 :         size_t len, octets, used_in_last_octet;
     464           0 :         uint64_t tag;
     465             : 
     466         192 :         len = strlen(s);
     467         192 :         if (len > MAX_SL_STRLEN) {
     468           0 :                 return -1;
     469             :         }
     470         192 :         octets = (len + 7) / 8;
     471         192 :         used_in_last_octet = len % 8;
     472         192 :         if (used_in_last_octet == 0) {
     473          14 :                 used_in_last_octet = 8;
     474             :         }
     475             : 
     476         192 :         tag = sl_pack_tag(SQ_CPX_TYPE_STRING, offset / 8, used_in_last_octet);
     477         192 :         result = sl_push_uint64_val(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, tag);
     478         192 :         if (result == -1) {
     479           0 :                 return -1;
     480             :         }
     481             : 
     482         192 :         tag = sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1);
     483         192 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     484         192 :         if (offset == -1) {
     485           0 :                 return -1;
     486             :         }
     487             : 
     488         192 :         *toc_idx += 1;
     489             : 
     490         192 :         tag = sl_pack_tag(SQ_TYPE_DATA, octets + 1, used_in_last_octet);
     491         192 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     492         192 :         if (offset == -1) {
     493           0 :                 return -1;
     494             :         }
     495             : 
     496         192 :         if (offset + (octets * 8) > bufsize) {
     497           0 :                 return -1;
     498             :         }
     499             : 
     500         192 :         memset(buf + offset, 0, octets * 8);
     501         192 :         memcpy(buf + offset, s, len);
     502         192 :         offset += octets * 8;
     503             : 
     504         192 :         return offset;
     505             : }
     506             : 
     507           2 : static ssize_t sl_pack_string_as_utf16(char *s, char *buf, ssize_t offset,
     508             :                                        size_t bufsize, char *toc_buf, int *toc_idx)
     509             : {
     510           0 :         ssize_t result;
     511           0 :         int utf16_plus_bom_len, octets, used_in_last_octet;
     512           2 :         char *utf16string = NULL;
     513           2 :         char bom[] = { 0xff, 0xfe };
     514           0 :         size_t slen, utf16len;
     515           0 :         uint64_t tag;
     516           0 :         bool ok;
     517             : 
     518           2 :         slen = strlen(s);
     519           2 :         if (slen > MAX_SL_STRLEN) {
     520           0 :                 return -1;
     521             :         }
     522             : 
     523           2 :         ok = convert_string_talloc(talloc_tos(),
     524             :                                    CH_UTF8,
     525             :                                    CH_UTF16LE,
     526             :                                    s,
     527             :                                    slen,
     528             :                                    &utf16string,
     529             :                                    &utf16len);
     530           2 :         if (!ok) {
     531           0 :                 return -1;
     532             :         }
     533             : 
     534           2 :         utf16_plus_bom_len = utf16len + 2;
     535           2 :         octets = (utf16_plus_bom_len + 7) / 8;
     536           2 :         used_in_last_octet = utf16_plus_bom_len % 8;
     537           2 :         if (used_in_last_octet == 0) {
     538           0 :                 used_in_last_octet = 8;
     539             :         }
     540             : 
     541           2 :         tag = sl_pack_tag(SQ_CPX_TYPE_UTF16_STRING, offset / 8, used_in_last_octet);
     542           2 :         result = sl_push_uint64_val(toc_buf, *toc_idx * 8, MAX_SLQ_TOC, tag);
     543           2 :         if (result == -1) {
     544           0 :                 offset = -1;
     545           0 :                 goto done;
     546             :         }
     547             : 
     548           2 :         tag = sl_pack_tag(SQ_TYPE_COMPLEX, 1, *toc_idx + 1);
     549           2 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     550           2 :         if (offset == -1) {
     551           0 :                 goto done;
     552             :         }
     553             : 
     554           2 :         *toc_idx += 1;
     555             : 
     556           2 :         tag = sl_pack_tag(SQ_TYPE_DATA, octets + 1, used_in_last_octet);
     557           2 :         offset = sl_push_uint64_val(buf, offset, bufsize, tag);
     558           2 :         if (offset == -1) {
     559           0 :                 goto done;
     560             :         }
     561             : 
     562           2 :         if (offset + (octets * 8) > bufsize) {
     563           0 :                 offset = -1;
     564           0 :                 goto done;
     565             :         }
     566             : 
     567           2 :         memset(buf + offset, 0, octets * 8);
     568           2 :         memcpy(buf + offset, &bom, sizeof(bom));
     569           2 :         memcpy(buf + offset + 2, utf16string, utf16len);
     570           2 :         offset += octets * 8;
     571             : 
     572           2 : done:
     573           2 :         TALLOC_FREE(utf16string);
     574           2 :         return offset;
     575             : }
     576             : 
     577         294 : static ssize_t sl_pack_loop(DALLOC_CTX *query, char *buf, ssize_t offset,
     578             :                             size_t bufsize, char *toc_buf, int *toc_idx, int *count)
     579             : {
     580           0 :         const char *type;
     581           0 :         int n;
     582           0 :         uint64_t i;
     583           0 :         sl_bool_t bl;
     584           0 :         double d;
     585           0 :         sl_time_t t;
     586           0 :         void *p;
     587             : 
     588         872 :         for (n = 0; n < dalloc_size(query); n++) {
     589             : 
     590         578 :                 type = dalloc_get_name(query, n);
     591         578 :                 if (type == NULL) {
     592           0 :                         return -1;
     593             :                 }
     594         578 :                 p = dalloc_get_object(query, n);
     595         578 :                 if (p == NULL) {
     596           0 :                         return -1;
     597             :                 }
     598             : 
     599         578 :                 if (strcmp(type, "sl_array_t") == 0) {
     600         196 :                         offset = sl_pack_array(p, buf, offset, bufsize,
     601             :                                                toc_buf, toc_idx);
     602         382 :                 } else if (strcmp(type, "sl_dict_t") == 0) {
     603          10 :                         offset = sl_pack_dict(p, buf, offset, bufsize,
     604             :                                               toc_buf, toc_idx, count);
     605         372 :                 } else if (strcmp(type, "sl_filemeta_t") == 0) {
     606          10 :                         offset = sl_pack_filemeta(p, buf, offset, bufsize,
     607             :                                                   toc_buf, toc_idx);
     608         362 :                 } else if (strcmp(type, "uint64_t") == 0) {
     609          44 :                         memcpy(&i, p, sizeof(uint64_t));
     610          44 :                         offset = sl_pack_uint64(i, buf, offset, bufsize);
     611         318 :                 } else if (strcmp(type, "uint64_t *") == 0) {
     612          58 :                         offset = sl_pack_uint64_array(p, buf, offset,
     613             :                                                       bufsize, count);
     614         260 :                 } else if (strcmp(type, "char *") == 0) {
     615         192 :                         offset = sl_pack_string(p, buf, offset, bufsize,
     616             :                                                 toc_buf, toc_idx);                                              
     617          68 :                 } else if (strcmp(type, "smb_ucs2_t *") == 0) {
     618           2 :                         offset = sl_pack_string_as_utf16(p, buf, offset, bufsize,
     619             :                                                          toc_buf, toc_idx);
     620          66 :                 } else if (strcmp(type, "sl_bool_t") == 0) {
     621           8 :                         memcpy(&bl, p, sizeof(sl_bool_t));
     622           8 :                         offset = sl_pack_bool(bl, buf, offset, bufsize);
     623          58 :                 } else if (strcmp(type, "double") == 0) {
     624           6 :                         memcpy(&d, p, sizeof(double));
     625           6 :                         offset = sl_pack_float(d, buf, offset, bufsize);
     626          52 :                 } else if (strcmp(type, "sl_nil_t") == 0) {
     627          10 :                         offset = sl_pack_nil(buf, offset, bufsize);
     628          42 :                 } else if (strcmp(type, "sl_time_t") == 0) {
     629           0 :                         memcpy(&t, p, sizeof(sl_time_t));
     630           0 :                         offset = sl_pack_date(t, buf, offset, bufsize);
     631          42 :                 } else if (strcmp(type, "sl_uuid_t") == 0) {
     632           4 :                         offset = sl_pack_uuid(p, buf, offset, bufsize);
     633          38 :                 } else if (strcmp(type, "sl_cnids_t") == 0) {
     634          38 :                         offset = sl_pack_CNID(p, buf, offset,
     635             :                                               bufsize, toc_buf, toc_idx);
     636             :                 } else {
     637           0 :                         DEBUG(1, ("unknown type: %s\n", type));
     638           0 :                         return -1;
     639             :                 }
     640         578 :                 if (offset == -1) {
     641           0 :                         DEBUG(1, ("error packing type: %s\n", type));
     642           0 :                         return -1;
     643             :                 }
     644             :         }
     645             : 
     646         294 :         return offset;
     647             : }
     648             : 
     649             : /******************************************************************************
     650             :  * unmarshalling functions
     651             :  ******************************************************************************/
     652             : 
     653        1865 : static ssize_t sl_unpack_tag(const char *buf,
     654             :                              ssize_t offset,
     655             :                              size_t bufsize,
     656             :                              uint encoding,
     657             :                              struct sl_tag *tag)
     658             : {
     659          11 :         uint64_t val;
     660             : 
     661        1865 :         if (offset + 8 > bufsize) {
     662           0 :                 DEBUG(1,("%s: buffer overflow\n", __func__));
     663           0 :                 return -1;
     664             :         }
     665             : 
     666        1865 :         if (encoding == SL_ENC_LITTLE_ENDIAN) {
     667        1865 :                 val = BVAL(buf, offset);
     668             :         } else {
     669           0 :                 val = RBVAL(buf, offset);
     670             :         }
     671             : 
     672        1865 :         tag->size = (val & 0xffff) * 8;
     673        1865 :         tag->type = (val & 0xffff0000) >> 16;
     674        1865 :         tag->count = val >> 32;
     675        1865 :         tag->length = tag->count * 8;
     676             : 
     677        1865 :         if (tag->size > MAX_MDSCMD_SIZE) {
     678           0 :                 DEBUG(1,("%s: size limit %zu\n", __func__, tag->size));
     679           0 :                 return -1;
     680             :         }
     681             : 
     682        1865 :         if (tag->length > MAX_MDSCMD_SIZE) {
     683           0 :                 DEBUG(1,("%s: length limit %zu\n", __func__, tag->length));
     684           0 :                 return -1;
     685             :         }
     686             : 
     687        1865 :         if (tag->count > MAX_SLQ_COUNT) {
     688           0 :                 DEBUG(1,("%s: count limit %d\n", __func__, tag->count));
     689           0 :                 return -1;
     690             :         }
     691             : 
     692        1854 :         return offset + 8;
     693             : }
     694             : 
     695         101 : static int sl_unpack_ints(DALLOC_CTX *query,
     696             :                           const char *buf,
     697             :                           ssize_t offset,
     698             :                           size_t bufsize,
     699             :                           int encoding)
     700             : {
     701           1 :         int i, result;
     702           1 :         struct sl_tag tag;
     703           1 :         uint64_t query_data64;
     704             : 
     705         101 :         offset = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
     706         101 :         if (offset == -1) {
     707           0 :                 return -1;
     708             :         }
     709             : 
     710         220 :         for (i = 0; i < tag.count; i++) {
     711         119 :                 offset = sl_pull_uint64_val(buf, offset, bufsize, encoding, &query_data64);
     712         119 :                 if (offset == -1) {
     713           0 :                         return -1;
     714             :                 }
     715         119 :                 result = dalloc_add_copy(query, &query_data64, uint64_t);
     716         119 :                 if (result != 0) {
     717           0 :                         return -1;
     718             :                 }
     719             :         }
     720             : 
     721         100 :         return tag.count;
     722             : }
     723             : 
     724           0 : static int sl_unpack_date(DALLOC_CTX *query,
     725             :                           const char *buf,
     726             :                           ssize_t offset,
     727             :                           size_t bufsize,
     728             :                           int encoding)
     729             : {
     730           0 :         int i, result;
     731           0 :         struct sl_tag tag;
     732           0 :         uint64_t query_data64;
     733           0 :         union {
     734             :                 double d;
     735             :                 uint64_t w;
     736             :         } ieee_fp_union;
     737           0 :         double fraction;
     738           0 :         sl_time_t t;
     739             : 
     740           0 :         offset = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
     741           0 :         if (offset == -1) {
     742           0 :                 return -1;
     743             :         }
     744             : 
     745           0 :         for (i = 0; i < tag.count; i++) {
     746           0 :                 offset = sl_pull_uint64_val(buf, offset, bufsize, encoding, &query_data64);
     747           0 :                 if (offset == -1) {
     748           0 :                         return -1;
     749             :                 }
     750           0 :                 ieee_fp_union.w = query_data64;
     751           0 :                 fraction = ieee_fp_union.d - (uint64_t)ieee_fp_union.d;
     752             : 
     753           0 :                 t = (sl_time_t) {
     754           0 :                         .tv_sec = ieee_fp_union.d + SPOTLIGHT_TIME_DELTA,
     755           0 :                         .tv_usec = fraction * 1000000
     756             :                 };
     757             : 
     758           0 :                 result = dalloc_add_copy(query, &t, sl_time_t);
     759           0 :                 if (result != 0) {
     760           0 :                         return -1;
     761             :                 }
     762             :         }
     763             : 
     764           0 :         return tag.count;
     765             : }
     766             : 
     767          20 : static int sl_unpack_uuid(DALLOC_CTX *query,
     768             :                           const char *buf,
     769             :                           ssize_t offset,
     770             :                           size_t bufsize,
     771             :                           int encoding)
     772             : {
     773           0 :         int i, result;
     774           0 :         sl_uuid_t uuid;
     775           0 :         struct sl_tag tag;
     776             : 
     777          20 :         offset = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
     778          20 :         if (offset == -1) {
     779           0 :                 return -1;
     780             :         }
     781             : 
     782          40 :         for (i = 0; i < tag.count; i++) {
     783          20 :                 if (offset + 16 > bufsize) {
     784           0 :                         DEBUG(1,("%s: buffer overflow\n", __func__));
     785           0 :                         return -1;
     786             :                 }
     787          20 :                 memcpy(uuid.sl_uuid, buf + offset, 16);
     788          20 :                 result = dalloc_add_copy(query, &uuid, sl_uuid_t);
     789          20 :                 if (result != 0) {
     790           0 :                         return -1;
     791             :                 }
     792          20 :                 offset += 16;
     793             :         }
     794             : 
     795          20 :         return tag.count;
     796             : }
     797             : 
     798           2 : static int sl_unpack_floats(DALLOC_CTX *query,
     799             :                             const char *buf,
     800             :                             ssize_t offset,
     801             :                             size_t bufsize,
     802             :                             int encoding)
     803             : {
     804           0 :         int i, result;
     805           0 :         union {
     806             :                 double d;
     807             :                 uint32_t w[2];
     808             :         } ieee_fp_union;
     809           0 :         struct sl_tag tag;
     810             : 
     811           2 :         offset = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
     812           2 :         if (offset == -1) {
     813           0 :                 return -1;
     814             :         }
     815             : 
     816           4 :         for (i = 0; i < tag.count; i++) {
     817           2 :                 if (offset + 8 > bufsize) {
     818           0 :                         DEBUG(1,("%s: buffer overflow\n", __func__));
     819           0 :                         return -1;
     820             :                 }
     821           2 :                 if (encoding == SL_ENC_LITTLE_ENDIAN) {
     822             : #ifdef WORDS_BIGENDIAN
     823             :                         ieee_fp_union.w[0] = IVAL(buf, offset + 4);
     824             :                         ieee_fp_union.w[1] = IVAL(buf, offset);
     825             : #else
     826           2 :                         ieee_fp_union.w[0] = IVAL(buf, offset);
     827           2 :                         ieee_fp_union.w[1] = IVAL(buf, offset + 4);
     828             : #endif
     829             :                 } else {
     830             : #ifdef WORDS_BIGENDIAN
     831             :                         ieee_fp_union.w[0] = RIVAL(buf, offset);
     832             :                         ieee_fp_union.w[1] = RIVAL(buf, offset + 4);
     833             : #else
     834           0 :                         ieee_fp_union.w[0] = RIVAL(buf, offset + 4);
     835           0 :                         ieee_fp_union.w[1] = RIVAL(buf, offset);
     836             : #endif
     837             :                 }
     838           2 :                 result = dalloc_add_copy(query, &ieee_fp_union.d, double);
     839           2 :                 if (result != 0) {
     840           0 :                         return -1;
     841             :                 }
     842           2 :                 offset += 8;
     843             :         }
     844             : 
     845           2 :         return tag.count;
     846             : }
     847             : 
     848          43 : static int sl_unpack_CNID(DALLOC_CTX *query,
     849             :                           const char *buf,
     850             :                           ssize_t offset,
     851             :                           size_t bufsize,
     852             :                           int length,
     853             :                           int encoding)
     854             : {
     855           1 :         int i, count, result;
     856           1 :         uint64_t query_data64;
     857           1 :         sl_cnids_t *cnids;
     858             : 
     859          43 :         cnids = talloc_zero(query, sl_cnids_t);
     860          43 :         if (cnids == NULL) {
     861           0 :                 return -1;
     862             :         }
     863          43 :         cnids->ca_cnids = dalloc_new(cnids);
     864          43 :         if (cnids->ca_cnids == NULL) {
     865           0 :                 return -1;
     866             :         }
     867             : 
     868          43 :         if (length < 8) {
     869           0 :                 return -1;
     870             :         }
     871          43 :         if (length == 8) {
     872             :                 /*
     873             :                  * That's permitted, length=8 is an empty CNID array.
     874             :                  */
     875           3 :                 result = dalloc_add(query, cnids, sl_cnids_t);
     876           3 :                 if (result != 0) {
     877           0 :                         return -1;
     878             :                 }
     879           3 :                 return 0;
     880             :         }
     881             : 
     882          40 :         offset = sl_pull_uint64_val(buf, offset, bufsize, encoding, &query_data64);
     883          40 :         if (offset == -1) {
     884           0 :                 return -1;
     885             :         }
     886             : 
     887             :         /*
     888             :          * Note: ca_unkn1 and ca_context could be taken from the tag
     889             :          * type and count members, but the fields are packed
     890             :          * differently in this context, so we can't use
     891             :          * sl_unpack_tag().
     892             :          */
     893          40 :         count = query_data64 & 0xffff;;
     894          40 :         cnids->ca_unkn1 = (query_data64 & 0xffff0000) >> 16;
     895          40 :         cnids->ca_context = query_data64 >> 32;
     896             : 
     897         100 :         for (i = 0; i < count; i++) {
     898          60 :                 offset = sl_pull_uint64_val(buf, offset, bufsize, encoding, &query_data64);
     899          60 :                 if (offset == -1) {
     900           0 :                         return -1;
     901             :                 }
     902             : 
     903          60 :                 result = dalloc_add_copy(cnids->ca_cnids, &query_data64, uint64_t);
     904          60 :                 if (result != 0) {
     905           0 :                         return -1;
     906             :                 }
     907             :         }
     908             : 
     909          40 :         result = dalloc_add(query, cnids, sl_cnids_t);
     910          40 :         if (result != 0) {
     911           0 :                 return -1;
     912             :         }
     913             : 
     914          40 :         return 0;
     915             : }
     916             : 
     917         549 : static ssize_t sl_unpack_cpx(DALLOC_CTX *query,
     918             :                              const char *buf,
     919             :                              ssize_t offset,
     920             :                              size_t bufsize,
     921             :                              int cpx_query_type,
     922             :                              int cpx_query_count,
     923             :                              ssize_t toc_offset,
     924             :                              int encoding)
     925             : {
     926           3 :         int result;
     927         549 :         ssize_t roffset = offset;
     928           3 :         int unicode_encoding;
     929           3 :         bool mark_exists;
     930           3 :         char *p;
     931           3 :         size_t slen, tmp_len;
     932           3 :         sl_array_t *sl_array;
     933           3 :         sl_dict_t *sl_dict;
     934           3 :         sl_filemeta_t *sl_fm;
     935           3 :         bool ok;
     936           3 :         struct sl_tag tag;
     937             : 
     938         549 :         switch (cpx_query_type) {
     939         199 :         case SQ_CPX_TYPE_ARRAY:
     940         199 :                 sl_array = dalloc_zero(query, sl_array_t);
     941         199 :                 if (sl_array == NULL) {
     942           0 :                         return -1;
     943             :                 }
     944         199 :                 roffset = sl_unpack_loop(sl_array, buf, offset, bufsize,
     945             :                                          cpx_query_count, toc_offset, encoding);
     946         199 :                 if (roffset == -1) {
     947           2 :                         return -1;
     948             :                 }
     949         197 :                 result = dalloc_add(query, sl_array, sl_array_t);
     950         197 :                 if (result != 0) {
     951           0 :                         return -1;
     952             :                 }
     953         196 :                 break;
     954             : 
     955          14 :         case SQ_CPX_TYPE_DICT:
     956          14 :                 sl_dict = dalloc_zero(query, sl_dict_t);
     957          14 :                 if (sl_dict == NULL) {
     958           0 :                         return -1;
     959             :                 }
     960          14 :                 roffset = sl_unpack_loop(sl_dict, buf, offset, bufsize,
     961             :                                          cpx_query_count, toc_offset, encoding);
     962          14 :                 if (roffset == -1) {
     963           0 :                         return -1;
     964             :                 }
     965          14 :                 result = dalloc_add(query, sl_dict, sl_dict_t);
     966          14 :                 if (result != 0) {
     967           0 :                         return -1;
     968             :                 }
     969          14 :                 break;
     970             : 
     971         256 :         case SQ_CPX_TYPE_STRING:
     972             :         case SQ_CPX_TYPE_UTF16_STRING:
     973         256 :                 offset = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
     974         256 :                 if (offset == -1) {
     975           0 :                         return -1;
     976             :                 }
     977             : 
     978         256 :                 if (tag.size < 16) {
     979           0 :                         DEBUG(1,("%s: string buffer too small\n", __func__));
     980           0 :                         return -1;
     981             :                 }
     982         256 :                 slen = tag.size - 16 + tag.count;
     983         256 :                 if (slen > MAX_MDSCMD_SIZE) {
     984           0 :                         return -1;
     985             :                 }
     986             : 
     987         256 :                 if (offset + slen > bufsize) {
     988           0 :                         DEBUG(1,("%s: buffer overflow\n", __func__));
     989           0 :                         return -1;
     990             :                 }
     991             : 
     992         256 :                 if (cpx_query_type == SQ_CPX_TYPE_STRING) {
     993         246 :                         p = talloc_strndup(query, buf + offset, slen);
     994         246 :                         if (p == NULL) {
     995           0 :                                 return -1;
     996             :                         }
     997             :                 } else {
     998          10 :                         unicode_encoding = spotlight_get_utf16_string_encoding(
     999             :                                 buf, offset, slen, encoding);
    1000          10 :                         mark_exists = (unicode_encoding & SL_ENC_UTF_16) ? true : false;
    1001          10 :                         if (unicode_encoding & SL_ENC_BIG_ENDIAN) {
    1002           0 :                                 DEBUG(1, ("Unsupported big endian UTF16 string\n"));
    1003           0 :                                 return -1;
    1004             :                         }
    1005          10 :                         slen -= mark_exists ? 2 : 0;
    1006          10 :                         ok = convert_string_talloc(
    1007             :                                 query,
    1008             :                                 CH_UTF16LE,
    1009             :                                 CH_UTF8,
    1010          10 :                                 buf + offset + (mark_exists ? 2 : 0),
    1011             :                                 slen,
    1012             :                                 &p,
    1013             :                                 &tmp_len);
    1014          10 :                         if (!ok) {
    1015           0 :                                 return -1;
    1016             :                         }
    1017             :                 }
    1018             : 
    1019         256 :                 result = dalloc_stradd(query, p);
    1020         256 :                 if (result != 0) {
    1021           0 :                         return -1;
    1022             :                 }
    1023         256 :                 roffset += tag.size;
    1024         256 :                 break;
    1025             : 
    1026          37 :         case SQ_CPX_TYPE_FILEMETA:
    1027          37 :                 offset = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
    1028          37 :                 if (offset == -1) {
    1029           0 :                         return -1;
    1030             :                 }
    1031          37 :                 if (tag.size < 8) {
    1032           0 :                         DBG_WARNING("size too mall: %zu\n", tag.size);
    1033           0 :                         return -1;
    1034             :                 }
    1035             : 
    1036          37 :                 sl_fm = dalloc_zero(query, sl_filemeta_t);
    1037          37 :                 if (sl_fm == NULL) {
    1038           0 :                         return -1;
    1039             :                 }
    1040             : 
    1041          37 :                 if (tag.size >= 16) {
    1042          34 :                         result = sl_unpack(sl_fm,
    1043             :                                            buf + offset,
    1044             :                                            bufsize - offset );
    1045          34 :                         if (result == -1) {
    1046           0 :                                 return -1;
    1047             :                         }
    1048             :                 }
    1049          37 :                 result = dalloc_add(query, sl_fm, sl_filemeta_t);
    1050          37 :                 if (result != 0) {
    1051           0 :                         return -1;
    1052             :                 }
    1053          37 :                 roffset += tag.size;
    1054          37 :                 break;
    1055             : 
    1056          43 :         case SQ_CPX_TYPE_CNIDS:
    1057          43 :                 offset = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
    1058          43 :                 if (offset == -1) {
    1059           0 :                         return -1;
    1060             :                 }
    1061             : 
    1062          44 :                 result = sl_unpack_CNID(query, buf, offset, bufsize,
    1063          43 :                                         tag.size, encoding);
    1064          43 :                 if (result == -1) {
    1065           0 :                         return -1;
    1066             :                 }
    1067          43 :                 roffset += tag.size;
    1068          43 :                 break;
    1069             : 
    1070           0 :         default:
    1071           0 :                 DEBUG(1, ("unknown complex query type: %u\n", cpx_query_type));
    1072           0 :                 return -1;
    1073             :         }
    1074             : 
    1075         544 :         return roffset;
    1076             : }
    1077             : 
    1078         320 : static ssize_t sl_unpack_loop(DALLOC_CTX *query,
    1079             :                               const char *buf,
    1080             :                               ssize_t offset,
    1081             :                               size_t bufsize,
    1082             :                               int count,
    1083             :                               ssize_t toc_offset,
    1084             :                               int encoding)
    1085             : {
    1086           2 :         int i, toc_index, subcount;
    1087           2 :         uint64_t result;
    1088             : 
    1089        1066 :         while (count > 0) {
    1090           4 :                 struct sl_tag tag;
    1091             : 
    1092         750 :                 if (offset >= toc_offset) {
    1093           4 :                         return -1;
    1094             :                 }
    1095             : 
    1096         750 :                 result = sl_unpack_tag(buf, offset, bufsize, encoding, &tag);
    1097         750 :                 if (result == -1) {
    1098           0 :                         return -1;
    1099             :                 }
    1100             : 
    1101         750 :                 switch (tag.type) {
    1102         549 :                 case SQ_TYPE_COMPLEX: {
    1103           3 :                         struct sl_tag cpx_tag;
    1104             : 
    1105         549 :                         if (tag.count < 1) {
    1106           0 :                                 DEBUG(1,("%s: invalid tag.count: %d\n",
    1107             :                                          __func__, tag.count));
    1108           2 :                                 return -1;
    1109             :                         }
    1110         549 :                         toc_index = tag.count - 1;
    1111         549 :                         if (toc_index > MAX_SLQ_TOCIDX) {
    1112           0 :                                 DEBUG(1,("%s: toc_index too large: %d\n",
    1113             :                                          __func__, toc_index));
    1114           0 :                                 return -1;
    1115             :                         }
    1116         549 :                         result = sl_unpack_tag(buf, toc_offset + (toc_index * 8),
    1117             :                                                bufsize, encoding, &cpx_tag);
    1118         549 :                         if (result == -1) {
    1119           0 :                                 return -1;
    1120             :                         }
    1121             : 
    1122         549 :                         offset = sl_unpack_cpx(query, buf, offset + 8, bufsize, cpx_tag.type,
    1123             :                                                cpx_tag.count, toc_offset, encoding);
    1124         549 :                         if (offset == -1) {
    1125           2 :                                 return -1;
    1126             :                         }
    1127             :                         /*
    1128             :                          * tag.size is not the size here, so we need
    1129             :                          * to use the offset returned from sl_unpack_cpx()
    1130             :                          * instead of offset += tag.size;
    1131             :                          */
    1132         547 :                         count--;
    1133         547 :                         break;
    1134             :                 }
    1135             : 
    1136          38 :                 case SQ_TYPE_NULL: {
    1137          38 :                         sl_nil_t nil = 0;
    1138             : 
    1139          38 :                         subcount = tag.count;
    1140          38 :                         if (subcount < 1 || subcount > count) {
    1141           2 :                                 return -1;
    1142             :                         }
    1143          72 :                         for (i = 0; i < subcount; i++) {
    1144          36 :                                 result = dalloc_add_copy(query, &nil, sl_nil_t);
    1145          36 :                                 if (result != 0) {
    1146           0 :                                         return -1;
    1147             :                                 }
    1148             :                         }
    1149          36 :                         offset += tag.size;
    1150          36 :                         count -= subcount;
    1151          36 :                         break;
    1152             :                 }
    1153             : 
    1154          40 :                 case SQ_TYPE_BOOL: {
    1155          40 :                         sl_bool_t b = (tag.count != 0);
    1156             : 
    1157          40 :                         result = dalloc_add_copy(query, &b, sl_bool_t);
    1158          40 :                         if (result != 0) {
    1159           0 :                                 return -1;
    1160             :                         }
    1161          40 :                         offset += tag.size;
    1162          40 :                         count--;
    1163          40 :                         break;
    1164             :                 }
    1165             : 
    1166         101 :                 case SQ_TYPE_INT64:
    1167         101 :                         subcount = sl_unpack_ints(query, buf, offset, bufsize, encoding);
    1168         101 :                         if (subcount < 1 || subcount > count) {
    1169           0 :                                 return -1;
    1170             :                         }
    1171         101 :                         offset += tag.size;
    1172         101 :                         count -= subcount;
    1173         101 :                         break;
    1174             : 
    1175          20 :                 case SQ_TYPE_UUID:
    1176          20 :                         subcount = sl_unpack_uuid(query, buf, offset, bufsize, encoding);
    1177          20 :                         if (subcount < 1 || subcount > count) {
    1178           0 :                                 return -1;
    1179             :                         }
    1180          20 :                         offset += tag.size;
    1181          20 :                         count -= subcount;
    1182          20 :                         break;
    1183             : 
    1184           2 :                 case SQ_TYPE_FLOAT:
    1185           2 :                         subcount = sl_unpack_floats(query, buf, offset, bufsize, encoding);
    1186           2 :                         if (subcount < 1 || subcount > count) {
    1187           0 :                                 return -1;
    1188             :                         }
    1189           2 :                         offset += tag.size;
    1190           2 :                         count -= subcount;
    1191           2 :                         break;
    1192             : 
    1193           0 :                 case SQ_TYPE_DATE:
    1194           0 :                         subcount = sl_unpack_date(query, buf, offset, bufsize, encoding);
    1195           0 :                         if (subcount < 1 || subcount > count) {
    1196           0 :                                 return -1;
    1197             :                         }
    1198           0 :                         offset += tag.size;
    1199           0 :                         count -= subcount;
    1200           0 :                         break;
    1201             : 
    1202           0 :                 default:
    1203           0 :                         DEBUG(1, ("unknown query type: %d\n", tag.type));
    1204           0 :                         return -1;
    1205             :                 }
    1206             :         }
    1207             : 
    1208         314 :         return offset;
    1209             : }
    1210             : 
    1211          88 : static ssize_t sl_pack(DALLOC_CTX *query, char *buf, size_t bufsize)
    1212             : {
    1213           0 :         ssize_t result;
    1214           0 :         char *toc_buf;
    1215          88 :         int toc_index = 0;
    1216          88 :         int toc_count = 0;
    1217           0 :         ssize_t offset, len;
    1218           0 :         uint64_t hdr;
    1219           0 :         uint32_t total_octets;
    1220           0 :         uint32_t data_octets;
    1221           0 :         uint64_t tag;
    1222             : 
    1223          88 :         memset(buf, 0, bufsize);
    1224             : 
    1225          88 :         toc_buf = talloc_zero_size(query, MAX_SLQ_TOC + 8);
    1226          88 :         if (toc_buf == NULL) {
    1227           0 :                 return -1;
    1228             :         }
    1229             : 
    1230          88 :         offset = sl_pack_loop(query, buf, 16, bufsize, toc_buf + 8, &toc_index, &toc_count);
    1231          88 :         if (offset == -1 || offset < 16) {
    1232           0 :                 DEBUG(10,("%s: sl_pack_loop error\n", __func__));
    1233           0 :                 return -1;
    1234             :         }
    1235          88 :         len = offset - 16;
    1236             : 
    1237             :         /*
    1238             :          * Marshalling overview:
    1239             :          *
    1240             :          * 16 bytes at the start of buf:
    1241             :          *
    1242             :          * 8 bytes byte order mark
    1243             :          * 4 bytes total octets
    1244             :          * 4 bytes table of content octets
    1245             :          *
    1246             :          * x bytes total octets * 8 from sl_pack_loop
    1247             :          * x bytes ToC octets * 8 from toc_buf
    1248             :          */
    1249             : 
    1250             :         /* Byte-order mark - we are using little endian only for now */
    1251          88 :         memcpy(buf, "432130dm", strlen("432130dm"));
    1252             : 
    1253             :         /*
    1254             :          * The data buffer and ToC buffer sizes are enocoded in number
    1255             :          * of octets (size / 8), plus one, because the octet encoding
    1256             :          * the sizes is included.
    1257             :          */
    1258          88 :         data_octets = (len / 8) + 1;
    1259          88 :         total_octets = data_octets + toc_index + 1;
    1260             : 
    1261          88 :         hdr = total_octets;
    1262          88 :         hdr |= ((uint64_t)data_octets << 32);
    1263             : 
    1264             :         /* HDR */
    1265          88 :         result = sl_push_uint64_val(buf, 8, bufsize, hdr);
    1266          88 :         if (result == -1) {
    1267           0 :                 return -1;
    1268             :         }
    1269             : 
    1270             :         /*
    1271             :          * ToC tag with number of ToC entries plus one, the ToC tag
    1272             :          * header.
    1273             :          */
    1274          88 :         tag = sl_pack_tag(SQ_TYPE_TOC, toc_index + 1, 0);
    1275          88 :         result = sl_push_uint64_val(toc_buf, 0, MAX_SLQ_TOC, tag);
    1276          88 :         if (result == -1) {
    1277           0 :                 return -1;
    1278             :         }
    1279             : 
    1280          88 :         if ((16 + len + ((toc_index + 1 ) * 8)) > bufsize) {
    1281           0 :                 DEBUG(1, ("%s: exceeding size limit %zu\n", __func__, bufsize));
    1282           0 :                 return -1;
    1283             :         }
    1284             : 
    1285          88 :         memcpy(buf + 16 + len, toc_buf, (toc_index + 1 ) * 8);
    1286          88 :         len += 16 + (toc_index + 1 ) * 8;
    1287             : 
    1288          88 :         return len;
    1289             : }
    1290             : 
    1291             : /******************************************************************************
    1292             :  * Global functions for packing und unpacking
    1293             :  ******************************************************************************/
    1294             : 
    1295          78 : NTSTATUS sl_pack_alloc(TALLOC_CTX *mem_ctx,
    1296             :                        DALLOC_CTX *d,
    1297             :                        struct mdssvc_blob *b,
    1298             :                        size_t max_fragment_size)
    1299             : {
    1300           0 :         ssize_t len;
    1301             : 
    1302          78 :         b->spotlight_blob = talloc_zero_array(mem_ctx,
    1303             :                                               uint8_t,
    1304             :                                               max_fragment_size);
    1305          78 :         if (b->spotlight_blob == NULL) {
    1306           0 :                 return NT_STATUS_NO_MEMORY;
    1307             :         }
    1308             : 
    1309          78 :         len = sl_pack(d, (char *)b->spotlight_blob, max_fragment_size);
    1310          78 :         if (len == -1) {
    1311           0 :                 return NT_STATUS_DATA_ERROR;
    1312             :         }
    1313             : 
    1314          78 :         b->length = len;
    1315          78 :         b->size = len;
    1316          78 :         return NT_STATUS_OK;
    1317             : }
    1318             : 
    1319         107 : bool sl_unpack(DALLOC_CTX *query, const char *buf, size_t bufsize)
    1320             : {
    1321           1 :         ssize_t result;
    1322         107 :         ssize_t offset = 0;
    1323           1 :         int encoding;
    1324           1 :         uint64_t hdr;
    1325           1 :         uint32_t total_octets;
    1326           1 :         uint64_t total_bytes;
    1327           1 :         uint32_t data_octets;
    1328           1 :         uint64_t data_bytes;
    1329           1 :         uint64_t toc_offset;
    1330           1 :         struct sl_tag toc_tag;
    1331             : 
    1332         107 :         if (bufsize > MAX_MDSCMD_SIZE) {
    1333           0 :                 return false;
    1334             :         }
    1335             : 
    1336         107 :         if (bufsize < 8) {
    1337           0 :                 return false;
    1338             :         }
    1339         107 :         if (strncmp(buf + offset, "md031234", 8) == 0) {
    1340           0 :                 encoding = SL_ENC_BIG_ENDIAN;
    1341             :         } else {
    1342         107 :                 encoding = SL_ENC_LITTLE_ENDIAN;
    1343             :         }
    1344         107 :         offset += 8;
    1345             : 
    1346         107 :         offset = sl_pull_uint64_val(buf, offset, bufsize, encoding, &hdr);
    1347         107 :         if (offset == -1) {
    1348           0 :                 return false;
    1349             :         }
    1350             : 
    1351         107 :         total_octets = hdr & UINT32_MAX;
    1352         107 :         data_octets = hdr >> 32;
    1353             : 
    1354             :         /*
    1355             :          * Both fields contain the number of octets of the
    1356             :          * corresponding buffer plus the tag octet. We adjust the
    1357             :          * values to match just the number of octets in the buffers.
    1358             :          */
    1359         107 :         if (total_octets < 1) {
    1360           0 :                 return false;
    1361             :         }
    1362         107 :         if (data_octets < 1) {
    1363           0 :                 return false;
    1364             :         }
    1365         107 :         total_octets--;
    1366         107 :         data_octets--;
    1367         107 :         data_bytes = ((uint64_t)data_octets) * 8;
    1368         107 :         total_bytes = ((uint64_t)total_octets) * 8;
    1369             : 
    1370         107 :         if (data_bytes >= total_bytes) {
    1371           0 :                 DEBUG(1,("%s: data_bytes: %" PRIu64 ", total_bytes: %" PRIu64 "\n",
    1372             :                          __func__, data_bytes, total_bytes));
    1373           0 :                 return false;
    1374             :         }
    1375             : 
    1376         107 :         if (total_bytes > (bufsize - offset)) {
    1377           0 :                 return false;
    1378             :         }
    1379             : 
    1380         107 :         toc_offset = data_bytes;
    1381             : 
    1382         107 :         toc_offset = sl_unpack_tag(buf + offset, toc_offset,
    1383             :                                    bufsize - offset, encoding, &toc_tag);
    1384         107 :         if (toc_offset == -1) {
    1385           0 :                 return false;
    1386             :         }
    1387             : 
    1388         107 :         if (toc_tag.type != SQ_TYPE_TOC) {
    1389           0 :                 DEBUG(1,("%s: unknown tag type %d\n", __func__, toc_tag.type));
    1390           0 :                 return false;
    1391             :         }
    1392             : 
    1393             :         /*
    1394             :          * Check toc_tag.size even though we don't use it when unmarshalling
    1395             :          */
    1396         107 :         if (toc_tag.size > MAX_SLQ_TOC) {
    1397           0 :                 DEBUG(1,("%s: bad size %zu\n", __func__, toc_tag.size));
    1398           0 :                 return false;
    1399             :         }
    1400         107 :         if (toc_tag.size > (total_bytes - data_bytes)) {
    1401           0 :                 DEBUG(1,("%s: bad size %zu\n", __func__, toc_tag.size));
    1402           0 :                 return false;
    1403             :         }
    1404             : 
    1405         107 :         if (toc_tag.count != 0) {
    1406           0 :                 DEBUG(1,("%s: bad count %u\n", __func__, toc_tag.count));
    1407           0 :                 return false;
    1408             :         }
    1409             : 
    1410             :         /*
    1411             :          * We already consumed 16 bytes from the buffer (BOM and size
    1412             :          * tag), so we start at buf + offset.
    1413             :          */
    1414         107 :         result = sl_unpack_loop(query, buf + offset, 0, bufsize - offset,
    1415             :                                 1, toc_offset, encoding);
    1416         107 :         if (result == -1) {
    1417           2 :                 DEBUG(1,("%s: sl_unpack_loop failed\n", __func__));
    1418           2 :                 return false;
    1419             :         }
    1420             : 
    1421         104 :         return true;
    1422             : }

Generated by: LCOV version 1.14