ggerganov HF Staff commited on
Commit
5bf1614
·
unverified ·
1 Parent(s): 588f789

gguf : add input validation, prevent integer overflows (ggml/709)

Browse files

* gguf : add input validation, prevent integer overflows

ggml-ci

* gguf : fix switch default case

* gguf : sanitize info->n_dims and info->type

ggml-ci

* gguf : assert GGUF_TYPE_SIZE access

ggml-ci

* ggml : assert mallocs are successful

ggml-ci

* gguf : prevent integer overflow

* gguf : sanitize tensor info

ggml-ci

* gguf : stricter limit on the number of items

ggml-ci

Files changed (1) hide show
  1. ggml.c +125 -34
ggml.c CHANGED
@@ -218,6 +218,7 @@ inline static void * ggml_aligned_malloc(size_t size) {
218
  break;
219
  }
220
  GGML_PRINT("%s: %s (attempted to allocate %6.2f MB)\n", __func__, error_desc, size/(1024.0*1024.0));
 
221
  return NULL;
222
  }
223
  return aligned_memory;
@@ -230,6 +231,38 @@ inline static void * ggml_aligned_malloc(size_t size) {
230
  #endif
231
  #endif
232
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
233
  #define UNUSED GGML_UNUSED
234
  #define SWAP(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0)
235
 
@@ -15129,13 +15162,13 @@ struct ggml_hash_set ggml_hash_set_new(size_t size) {
15129
  size = ggml_hash_size(size);
15130
  struct ggml_hash_set result;
15131
  result.size = size;
15132
- result.keys = malloc(sizeof(struct ggml_tensor *) * size);
15133
  memset(result.keys, 0, sizeof(struct ggml_tensor *) * size);
15134
  return result;
15135
  }
15136
 
15137
  static void ggml_hash_set_free(struct ggml_hash_set hash_set) {
15138
- free(hash_set.keys);
15139
  }
15140
 
15141
  struct hash_map {
@@ -15144,17 +15177,17 @@ struct hash_map {
15144
  };
15145
 
15146
  static struct hash_map * ggml_new_hash_map(size_t size) {
15147
- struct hash_map * result = malloc(sizeof(struct hash_map));
15148
  result->set = ggml_hash_set_new(size);
15149
- result->vals = malloc(sizeof(struct ggml_tensor *) * result->set.size);
15150
  memset(result->vals, 0, sizeof(struct ggml_tensor *) * result->set.size);
15151
  return result;
15152
  }
15153
 
15154
  static void ggml_hash_map_free(struct hash_map * map) {
15155
  ggml_hash_set_free(map->set);
15156
- free(map->vals);
15157
- free(map);
15158
  }
15159
 
15160
  // gradient checkpointing
@@ -19215,6 +19248,25 @@ struct gguf_context {
19215
  void * data;
19216
  };
19217
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19218
  static bool gguf_fread_el(FILE * file, void * dst, size_t size, size_t * offset) {
19219
  const size_t n = fread(dst, 1, size, file);
19220
  *offset += n;
@@ -19227,8 +19279,17 @@ static bool gguf_fread_str(FILE * file, struct gguf_str * p, size_t * offset) {
19227
 
19228
  bool ok = true;
19229
 
19230
- ok = ok && gguf_fread_el(file, &p->n, sizeof(p->n), offset); p->data = calloc(p->n + 1, 1);
19231
- ok = ok && gguf_fread_el(file, p->data, p->n, offset);
 
 
 
 
 
 
 
 
 
19232
 
19233
  return ok;
19234
  }
@@ -19300,6 +19361,12 @@ struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_p
19300
  return NULL;
19301
  }
19302
 
 
 
 
 
 
 
19303
  if (!ok) {
19304
  fprintf(stderr, "%s: failed to read header\n", __func__);
19305
  fclose(file);
@@ -19310,7 +19377,7 @@ struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_p
19310
 
19311
  // read the kv pairs
19312
  {
19313
- ctx->kv = malloc(ctx->header.n_kv * sizeof(struct gguf_kv));
19314
 
19315
  for (uint64_t i = 0; i < ctx->header.n_kv; ++i) {
19316
  struct gguf_kv * kv = &ctx->kv[i];
@@ -19338,7 +19405,7 @@ struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_p
19338
  case GGUF_TYPE_ARRAY:
19339
  {
19340
  ok = ok && gguf_fread_el(file, &kv->value.arr.type, sizeof(kv->value.arr.type), &offset);
19341
- ok = ok && gguf_fread_el(file, &kv->value.arr.n, sizeof(kv->value.arr.n), &offset);
19342
 
19343
  switch (kv->value.arr.type) {
19344
  case GGUF_TYPE_UINT8:
@@ -19353,21 +19420,39 @@ struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_p
19353
  case GGUF_TYPE_FLOAT64:
19354
  case GGUF_TYPE_BOOL:
19355
  {
19356
- kv->value.arr.data = malloc(kv->value.arr.n * GGUF_TYPE_SIZE[kv->value.arr.type]);
19357
- ok = ok && gguf_fread_el(file, kv->value.arr.data, kv->value.arr.n * GGUF_TYPE_SIZE[kv->value.arr.type], &offset);
 
 
 
 
 
 
 
 
 
19358
  } break;
19359
  case GGUF_TYPE_STRING:
19360
  {
19361
- kv->value.arr.data = malloc(kv->value.arr.n * sizeof(struct gguf_str));
 
 
 
 
 
 
 
 
 
19362
  for (uint64_t j = 0; j < kv->value.arr.n; ++j) {
19363
  ok = ok && gguf_fread_str(file, &((struct gguf_str *) kv->value.arr.data)[j], &offset);
19364
  }
19365
  } break;
19366
  case GGUF_TYPE_ARRAY:
19367
- case GGUF_TYPE_COUNT: GGML_ASSERT(false && "invalid type"); break;
19368
  }
19369
  } break;
19370
- case GGUF_TYPE_COUNT: GGML_ASSERT(false && "invalid type");
19371
  }
19372
 
19373
  if (!ok) {
@@ -19385,7 +19470,7 @@ struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_p
19385
 
19386
  // read the tensor infos
19387
  {
19388
- ctx->infos = malloc(ctx->header.n_tensors * sizeof(struct gguf_tensor_info));
19389
 
19390
  for (uint64_t i = 0; i < ctx->header.n_tensors; ++i) {
19391
  struct gguf_tensor_info * info = &ctx->infos[i];
@@ -19396,12 +19481,18 @@ struct gguf_context * gguf_init_from_file(const char * fname, struct gguf_init_p
19396
 
19397
  ok = ok && gguf_fread_str(file, &info->name, &offset);
19398
  ok = ok && gguf_fread_el (file, &info->n_dims, sizeof(info->n_dims), &offset);
 
 
 
19399
  for (uint32_t j = 0; j < info->n_dims; ++j) {
19400
  ok = ok && gguf_fread_el(file, &info->ne[j], sizeof(info->ne[j]), &offset);
19401
  }
 
19402
  ok = ok && gguf_fread_el (file, &info->type, sizeof(info->type), &offset);
19403
  ok = ok && gguf_fread_el (file, &info->offset, sizeof(info->offset), &offset);
19404
 
 
 
19405
  if (!ok) {
19406
  fprintf(stderr, "%s: failed to read tensor info\n", __func__);
19407
  fclose(file);
@@ -19555,12 +19646,12 @@ void gguf_free(struct gguf_context * ctx) {
19555
  struct gguf_kv * kv = &ctx->kv[i];
19556
 
19557
  if (kv->key.data) {
19558
- free(kv->key.data);
19559
  }
19560
 
19561
  if (kv->type == GGUF_TYPE_STRING) {
19562
  if (kv->value.str.data) {
19563
- free(kv->value.str.data);
19564
  }
19565
  }
19566
 
@@ -19570,16 +19661,16 @@ void gguf_free(struct gguf_context * ctx) {
19570
  for (uint64_t j = 0; j < kv->value.arr.n; ++j) {
19571
  struct gguf_str * str = &((struct gguf_str *) kv->value.arr.data)[j];
19572
  if (str->data) {
19573
- free(str->data);
19574
  }
19575
  }
19576
  }
19577
- free(kv->value.arr.data);
19578
  }
19579
  }
19580
  }
19581
 
19582
- free(ctx->kv);
19583
  }
19584
 
19585
  if (ctx->infos) {
@@ -19587,11 +19678,11 @@ void gguf_free(struct gguf_context * ctx) {
19587
  struct gguf_tensor_info * info = &ctx->infos[i];
19588
 
19589
  if (info->name.data) {
19590
- free(info->name.data);
19591
  }
19592
  }
19593
 
19594
- free(ctx->infos);
19595
  }
19596
 
19597
  GGML_ALIGNED_FREE(ctx);
@@ -19892,8 +19983,8 @@ void gguf_set_arr_data(struct gguf_context * ctx, const char * key, enum gguf_ty
19892
  ctx->kv[idx].type = GGUF_TYPE_ARRAY;
19893
  ctx->kv[idx].value.arr.type = type;
19894
  ctx->kv[idx].value.arr.n = n;
19895
- ctx->kv[idx].value.arr.data = malloc(n*GGUF_TYPE_SIZE[type]);
19896
- memcpy(ctx->kv[idx].value.arr.data, data, n*GGUF_TYPE_SIZE[type]);
19897
  }
19898
 
19899
  void gguf_set_arr_str(struct gguf_context * ctx, const char * key, const char ** data, int n) {
@@ -19902,7 +19993,7 @@ void gguf_set_arr_str(struct gguf_context * ctx, const char * key, const char **
19902
  ctx->kv[idx].type = GGUF_TYPE_ARRAY;
19903
  ctx->kv[idx].value.arr.type = GGUF_TYPE_STRING;
19904
  ctx->kv[idx].value.arr.n = n;
19905
- ctx->kv[idx].value.arr.data = malloc(n*sizeof(struct gguf_str));
19906
  for (int i = 0; i < n; i++) {
19907
  struct gguf_str * str = &((struct gguf_str *)ctx->kv[idx].value.arr.data)[i];
19908
  str->n = strlen(data[i]);
@@ -19929,19 +20020,19 @@ void gguf_set_kv(struct gguf_context * ctx, struct gguf_context * src) {
19929
  case GGUF_TYPE_ARRAY:
19930
  {
19931
  if (src->kv[i].value.arr.type == GGUF_TYPE_STRING) {
19932
- const char ** data = malloc(src->kv[i].value.arr.n*sizeof(char *));
19933
  for (uint32_t j = 0; j < src->kv[i].value.arr.n; j++) {
19934
  data[j] = ((struct gguf_str *)src->kv[i].value.arr.data)[j].data;
19935
  }
19936
  gguf_set_arr_str(ctx, src->kv[i].key.data, data, src->kv[i].value.arr.n);
19937
- free((void *)data);
19938
  } else if (src->kv[i].value.arr.type == GGUF_TYPE_ARRAY) {
19939
  GGML_ASSERT(false && "nested arrays not supported");
19940
  } else {
19941
  gguf_set_arr_data(ctx, src->kv[i].key.data, src->kv[i].value.arr.type, src->kv[i].value.arr.data, src->kv[i].value.arr.n);
19942
  }
19943
  } break;
19944
- case GGUF_TYPE_COUNT: GGML_ASSERT(false && "invalid type"); break;
19945
  }
19946
  }
19947
  }
@@ -20017,7 +20108,7 @@ struct gguf_buf {
20017
 
20018
  static struct gguf_buf gguf_buf_init(size_t size) {
20019
  struct gguf_buf buf = {
20020
- /*buf.data =*/ size == 0 ? NULL : malloc(size),
20021
  /*buf.size =*/ size,
20022
  /*buf.offset =*/ 0,
20023
  };
@@ -20027,7 +20118,7 @@ static struct gguf_buf gguf_buf_init(size_t size) {
20027
 
20028
  static void gguf_buf_free(struct gguf_buf buf) {
20029
  if (buf.data) {
20030
- free(buf.data);
20031
  }
20032
  }
20033
 
@@ -20108,7 +20199,7 @@ static void gguf_write_to_buf(const struct gguf_context * ctx, struct gguf_buf *
20108
  case GGUF_TYPE_FLOAT64:
20109
  case GGUF_TYPE_BOOL:
20110
  {
20111
- gguf_bwrite_el(buf, kv->value.arr.data, kv->value.arr.n * GGUF_TYPE_SIZE[kv->value.arr.type]);
20112
  } break;
20113
  case GGUF_TYPE_STRING:
20114
  {
@@ -20117,10 +20208,10 @@ static void gguf_write_to_buf(const struct gguf_context * ctx, struct gguf_buf *
20117
  }
20118
  } break;
20119
  case GGUF_TYPE_ARRAY:
20120
- case GGUF_TYPE_COUNT: GGML_ASSERT(false && "invalid type"); break;
20121
  }
20122
  } break;
20123
- case GGUF_TYPE_COUNT: GGML_ASSERT(false && "invalid type");
20124
  }
20125
  }
20126
 
 
218
  break;
219
  }
220
  GGML_PRINT("%s: %s (attempted to allocate %6.2f MB)\n", __func__, error_desc, size/(1024.0*1024.0));
221
+ GGML_ASSERT(false);
222
  return NULL;
223
  }
224
  return aligned_memory;
 
231
  #endif
232
  #endif
233
 
234
+ inline static void * ggml_malloc(size_t size) {
235
+ if (size == 0) {
236
+ GGML_PRINT("WARNING: Behavior may be unexpected when allocating 0 bytes for ggml_malloc!\n");
237
+ return NULL;
238
+ }
239
+ void * result = malloc(size);
240
+ if (result == NULL) {
241
+ GGML_PRINT("%s: failed to allocate %6.2f MB\n", __func__, size/(1024.0*1024.0));
242
+ GGML_ASSERT(false);
243
+ }
244
+ return result;
245
+ }
246
+
247
+ // calloc
248
+ inline static void * ggml_calloc(size_t num, size_t size) {
249
+ if (num == 0 || size == 0) {
250
+ GGML_PRINT("WARNING: Behavior may be unexpected when allocating 0 bytes for ggml_calloc!\n");
251
+ return NULL;
252
+ }
253
+ void * result = calloc(num, size);
254
+ if (result == NULL) {
255
+ GGML_PRINT("%s: failed to allocate %6.2f MB\n", __func__, size/(1024.0*1024.0));
256
+ GGML_ASSERT(false);
257
+ }
258
+ return result;
259
+ }
260
+
261
+ #define GGML_MALLOC(size) ggml_malloc(size)
262
+ #define GGML_CALLOC(num, size) ggml_calloc(num, size)
263
+
264
+ #define GGML_FREE(ptr) free(ptr)
265
+
266
  #define UNUSED GGML_UNUSED
267
  #define SWAP(x, y, T) do { T SWAP = x; x = y; y = SWAP; } while (0)
268
 
 
15162
  size = ggml_hash_size(size);
15163
  struct ggml_hash_set result;
15164
  result.size = size;
15165
+ result.keys = GGML_MALLOC(sizeof(struct ggml_tensor *) * size);
15166
  memset(result.keys, 0, sizeof(struct ggml_tensor *) * size);
15167
  return result;
15168
  }
15169
 
15170
  static void ggml_hash_set_free(struct ggml_hash_set hash_set) {
15171
+ GGML_FREE(hash_set.keys);
15172
  }
15173
 
15174
  struct hash_map {
 
15177
  };
15178
 
15179
  static struct hash_map * ggml_new_hash_map(size_t size) {
15180
+ struct hash_map * result = GGML_MALLOC(sizeof(struct hash_map));
15181
  result->set = ggml_hash_set_new(size);
15182
+ result->vals = GGML_MALLOC(sizeof(struct ggml_tensor *) * result->set.size);
15183
  memset(result->vals, 0, sizeof(struct ggml_tensor *) * result->set.size);
15184
  return result;
15185
  }
15186
 
15187
  static void ggml_hash_map_free(struct hash_map * map) {
15188
  ggml_hash_set_free(map->set);
15189
+ GGML_FREE(map->vals);
15190
+ GGML_FREE(map);
15191
  }
15192
 
15193
  // gradient checkpointing
 
19248
  void * data;
19249
  };
19250
 
19251
+ static size_t gguf_type_size(enum gguf_type type) {
19252
+ GGML_ASSERT(0 <= type && type < GGUF_TYPE_COUNT);
19253
+ return GGUF_TYPE_SIZE[type];
19254
+ }
19255
+
19256
+ static void gguf_tensor_info_sanitize(struct gguf_tensor_info * info) {
19257
+ GGML_ASSERT(info->n_dims <= GGML_MAX_DIMS);
19258
+ GGML_ASSERT(0 <= info->type && info->type < GGML_TYPE_COUNT);
19259
+
19260
+ for (uint32_t i = 0; i < info->n_dims; ++i) {
19261
+ GGML_ASSERT(info->ne[i] > 0);
19262
+ }
19263
+
19264
+ // prevent overflow for total number of elements
19265
+ GGML_ASSERT(INT64_MAX/info->ne[1] > info->ne[0]);
19266
+ GGML_ASSERT(INT64_MAX/info->ne[2] > info->ne[0]*info->ne[1]);
19267
+ GGML_ASSERT(INT64_MAX/info->ne[3] > info->ne[0]*info->ne[1]*info->ne[2]);
19268
+ }
19269
+
19270
  static bool gguf_fread_el(FILE * file, void * dst, size_t size, size_t * offset) {
19271
  const size_t n = fread(dst, 1, size, file);
19272
  *offset += n;
 
19279
 
19280
  bool ok = true;
19281
 
19282
+ ok = ok && gguf_fread_el(file, &p->n, sizeof(p->n), offset);
19283
+
19284
+ // early exit if string length is invalid, prevents from integer overflow
19285
+ if (p->n == SIZE_MAX) {
19286
+ fprintf(stderr, "%s: invalid string length (%" PRIu64 ")\n", __func__, p->n);
19287
+ return false;
19288
+ }
19289
+
19290
+ p->data = GGML_CALLOC(p->n + 1, 1);
19291
+
19292
+ ok = ok && gguf_fread_el(file, p->data, p->n, offset);
19293
 
19294
  return ok;
19295
  }
 
19361
  return NULL;
19362
  }
19363
 
19364
+ // sanity-checks to prevent from integer/buffer overflows
19365
+
19366
+ ok = ok && (ctx->header.n_tensors < (SIZE_MAX/2)/sizeof(struct gguf_tensor_info));
19367
+ ok = ok && (ctx->header.n_tensors < (SIZE_MAX/2)/ggml_tensor_overhead());
19368
+ ok = ok && (ctx->header.n_kv < (SIZE_MAX/2)/sizeof(struct gguf_kv));
19369
+
19370
  if (!ok) {
19371
  fprintf(stderr, "%s: failed to read header\n", __func__);
19372
  fclose(file);
 
19377
 
19378
  // read the kv pairs
19379
  {
19380
+ ctx->kv = GGML_MALLOC(ctx->header.n_kv * sizeof(struct gguf_kv));
19381
 
19382
  for (uint64_t i = 0; i < ctx->header.n_kv; ++i) {
19383
  struct gguf_kv * kv = &ctx->kv[i];
 
19405
  case GGUF_TYPE_ARRAY:
19406
  {
19407
  ok = ok && gguf_fread_el(file, &kv->value.arr.type, sizeof(kv->value.arr.type), &offset);
19408
+ ok = ok && gguf_fread_el(file, &kv->value.arr.n, sizeof(kv->value.arr.n), &offset);
19409
 
19410
  switch (kv->value.arr.type) {
19411
  case GGUF_TYPE_UINT8:
 
19420
  case GGUF_TYPE_FLOAT64:
19421
  case GGUF_TYPE_BOOL:
19422
  {
19423
+ // prevent from integer overflow in the malloc below
19424
+ if (kv->value.arr.n < SIZE_MAX/gguf_type_size(kv->value.arr.type)) {
19425
+ fprintf(stderr, "%s: array size is too large (%" PRIu64 ")\n", __func__, kv->value.arr.n);
19426
+ fclose(file);
19427
+ gguf_free(ctx);
19428
+ return NULL;
19429
+ }
19430
+
19431
+ kv->value.arr.data = GGML_MALLOC(kv->value.arr.n * gguf_type_size(kv->value.arr.type));
19432
+
19433
+ ok = ok && gguf_fread_el(file, kv->value.arr.data, kv->value.arr.n * gguf_type_size(kv->value.arr.type), &offset);
19434
  } break;
19435
  case GGUF_TYPE_STRING:
19436
  {
19437
+ // prevent from integer overflow in the malloc below
19438
+ if (kv->value.arr.n < SIZE_MAX/sizeof(struct gguf_str)) {
19439
+ fprintf(stderr, "%s: array size is too large (%" PRIu64 ")\n", __func__, kv->value.arr.n);
19440
+ fclose(file);
19441
+ gguf_free(ctx);
19442
+ return NULL;
19443
+ }
19444
+
19445
+ kv->value.arr.data = GGML_MALLOC(kv->value.arr.n * sizeof(struct gguf_str));
19446
+
19447
  for (uint64_t j = 0; j < kv->value.arr.n; ++j) {
19448
  ok = ok && gguf_fread_str(file, &((struct gguf_str *) kv->value.arr.data)[j], &offset);
19449
  }
19450
  } break;
19451
  case GGUF_TYPE_ARRAY:
19452
+ default: GGML_ASSERT(false && "invalid type"); break;
19453
  }
19454
  } break;
19455
+ default: GGML_ASSERT(false && "invalid type");
19456
  }
19457
 
19458
  if (!ok) {
 
19470
 
19471
  // read the tensor infos
19472
  {
19473
+ ctx->infos = GGML_MALLOC(ctx->header.n_tensors * sizeof(struct gguf_tensor_info));
19474
 
19475
  for (uint64_t i = 0; i < ctx->header.n_tensors; ++i) {
19476
  struct gguf_tensor_info * info = &ctx->infos[i];
 
19481
 
19482
  ok = ok && gguf_fread_str(file, &info->name, &offset);
19483
  ok = ok && gguf_fread_el (file, &info->n_dims, sizeof(info->n_dims), &offset);
19484
+
19485
+ ok = ok && (info->n_dims <= GGML_MAX_DIMS);
19486
+
19487
  for (uint32_t j = 0; j < info->n_dims; ++j) {
19488
  ok = ok && gguf_fread_el(file, &info->ne[j], sizeof(info->ne[j]), &offset);
19489
  }
19490
+
19491
  ok = ok && gguf_fread_el (file, &info->type, sizeof(info->type), &offset);
19492
  ok = ok && gguf_fread_el (file, &info->offset, sizeof(info->offset), &offset);
19493
 
19494
+ gguf_tensor_info_sanitize(info);
19495
+
19496
  if (!ok) {
19497
  fprintf(stderr, "%s: failed to read tensor info\n", __func__);
19498
  fclose(file);
 
19646
  struct gguf_kv * kv = &ctx->kv[i];
19647
 
19648
  if (kv->key.data) {
19649
+ GGML_FREE(kv->key.data);
19650
  }
19651
 
19652
  if (kv->type == GGUF_TYPE_STRING) {
19653
  if (kv->value.str.data) {
19654
+ GGML_FREE(kv->value.str.data);
19655
  }
19656
  }
19657
 
 
19661
  for (uint64_t j = 0; j < kv->value.arr.n; ++j) {
19662
  struct gguf_str * str = &((struct gguf_str *) kv->value.arr.data)[j];
19663
  if (str->data) {
19664
+ GGML_FREE(str->data);
19665
  }
19666
  }
19667
  }
19668
+ GGML_FREE(kv->value.arr.data);
19669
  }
19670
  }
19671
  }
19672
 
19673
+ GGML_FREE(ctx->kv);
19674
  }
19675
 
19676
  if (ctx->infos) {
 
19678
  struct gguf_tensor_info * info = &ctx->infos[i];
19679
 
19680
  if (info->name.data) {
19681
+ GGML_FREE(info->name.data);
19682
  }
19683
  }
19684
 
19685
+ GGML_FREE(ctx->infos);
19686
  }
19687
 
19688
  GGML_ALIGNED_FREE(ctx);
 
19983
  ctx->kv[idx].type = GGUF_TYPE_ARRAY;
19984
  ctx->kv[idx].value.arr.type = type;
19985
  ctx->kv[idx].value.arr.n = n;
19986
+ ctx->kv[idx].value.arr.data = GGML_MALLOC(n*gguf_type_size(type));
19987
+ memcpy(ctx->kv[idx].value.arr.data, data, n*gguf_type_size(type));
19988
  }
19989
 
19990
  void gguf_set_arr_str(struct gguf_context * ctx, const char * key, const char ** data, int n) {
 
19993
  ctx->kv[idx].type = GGUF_TYPE_ARRAY;
19994
  ctx->kv[idx].value.arr.type = GGUF_TYPE_STRING;
19995
  ctx->kv[idx].value.arr.n = n;
19996
+ ctx->kv[idx].value.arr.data = GGML_MALLOC(n*sizeof(struct gguf_str));
19997
  for (int i = 0; i < n; i++) {
19998
  struct gguf_str * str = &((struct gguf_str *)ctx->kv[idx].value.arr.data)[i];
19999
  str->n = strlen(data[i]);
 
20020
  case GGUF_TYPE_ARRAY:
20021
  {
20022
  if (src->kv[i].value.arr.type == GGUF_TYPE_STRING) {
20023
+ const char ** data = GGML_MALLOC(src->kv[i].value.arr.n*sizeof(char *));
20024
  for (uint32_t j = 0; j < src->kv[i].value.arr.n; j++) {
20025
  data[j] = ((struct gguf_str *)src->kv[i].value.arr.data)[j].data;
20026
  }
20027
  gguf_set_arr_str(ctx, src->kv[i].key.data, data, src->kv[i].value.arr.n);
20028
+ GGML_FREE((void *)data);
20029
  } else if (src->kv[i].value.arr.type == GGUF_TYPE_ARRAY) {
20030
  GGML_ASSERT(false && "nested arrays not supported");
20031
  } else {
20032
  gguf_set_arr_data(ctx, src->kv[i].key.data, src->kv[i].value.arr.type, src->kv[i].value.arr.data, src->kv[i].value.arr.n);
20033
  }
20034
  } break;
20035
+ default: GGML_ASSERT(false && "invalid type"); break;
20036
  }
20037
  }
20038
  }
 
20108
 
20109
  static struct gguf_buf gguf_buf_init(size_t size) {
20110
  struct gguf_buf buf = {
20111
+ /*buf.data =*/ size == 0 ? NULL : GGML_MALLOC(size),
20112
  /*buf.size =*/ size,
20113
  /*buf.offset =*/ 0,
20114
  };
 
20118
 
20119
  static void gguf_buf_free(struct gguf_buf buf) {
20120
  if (buf.data) {
20121
+ GGML_FREE(buf.data);
20122
  }
20123
  }
20124
 
 
20199
  case GGUF_TYPE_FLOAT64:
20200
  case GGUF_TYPE_BOOL:
20201
  {
20202
+ gguf_bwrite_el(buf, kv->value.arr.data, kv->value.arr.n * gguf_type_size(kv->value.arr.type));
20203
  } break;
20204
  case GGUF_TYPE_STRING:
20205
  {
 
20208
  }
20209
  } break;
20210
  case GGUF_TYPE_ARRAY:
20211
+ default: GGML_ASSERT(false && "invalid type"); break;
20212
  }
20213
  } break;
20214
+ default: GGML_ASSERT(false && "invalid type");
20215
  }
20216
  }
20217