Spaces:
Sleeping
Sleeping
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
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 =
|
| 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 |
-
|
| 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 =
|
| 15148 |
result->set = ggml_hash_set_new(size);
|
| 15149 |
-
result->vals =
|
| 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 |
-
|
| 15157 |
-
|
| 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,
|
| 19231 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 =
|
| 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),
|
| 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 |
-
|
| 19357 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19358 |
} break;
|
| 19359 |
case GGUF_TYPE_STRING:
|
| 19360 |
{
|
| 19361 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 19368 |
}
|
| 19369 |
} break;
|
| 19370 |
-
|
| 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 =
|
| 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 |
-
|
| 19559 |
}
|
| 19560 |
|
| 19561 |
if (kv->type == GGUF_TYPE_STRING) {
|
| 19562 |
if (kv->value.str.data) {
|
| 19563 |
-
|
| 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 |
-
|
| 19574 |
}
|
| 19575 |
}
|
| 19576 |
}
|
| 19577 |
-
|
| 19578 |
}
|
| 19579 |
}
|
| 19580 |
}
|
| 19581 |
|
| 19582 |
-
|
| 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 |
-
|
| 19591 |
}
|
| 19592 |
}
|
| 19593 |
|
| 19594 |
-
|
| 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 =
|
| 19896 |
-
memcpy(ctx->kv[idx].value.arr.data, data, n*
|
| 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 =
|
| 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 =
|
| 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 |
-
|
| 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 |
-
|
| 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 :
|
| 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 |
-
|
| 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 *
|
| 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 |
-
|
| 20121 |
}
|
| 20122 |
} break;
|
| 20123 |
-
|
| 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 |
|