@@ -973,8 +973,21 @@ bool rpc_server::buffer_clear(const rpc_msg_buffer_clear_req & request) {
973
973
}
974
974
975
975
ggml_tensor * rpc_server::deserialize_tensor (struct ggml_context * ctx, const rpc_tensor * tensor) {
976
+ // Validate tensor type before using it
977
+ if (tensor->type < 0 || tensor->type >= GGML_TYPE_COUNT) {
978
+ GGML_LOG_ERROR (" [%s] invalid tensor type received: %u\n " , __func__, tensor->type );
979
+ return nullptr ;
980
+ }
981
+
976
982
ggml_tensor * result = ggml_new_tensor_4d (ctx, (ggml_type) tensor->type ,
977
983
tensor->ne [0 ], tensor->ne [1 ], tensor->ne [2 ], tensor->ne [3 ]);
984
+
985
+ // ggml_new_tensor_4d might fail if dimensions are invalid, although less likely to crash than invalid type
986
+ if (result == nullptr ) {
987
+ GGML_LOG_ERROR (" [%s] ggml_new_tensor_4d failed for type %u\\ n" , __func__, tensor->type );
988
+ return nullptr ;
989
+ }
990
+
978
991
for (uint32_t i = 0 ; i < GGML_MAX_DIMS; i++) {
979
992
result->nb [i] = tensor->nb [i];
980
993
}
@@ -1034,7 +1047,10 @@ bool rpc_server::set_tensor(const std::vector<uint8_t> & input) {
1034
1047
const size_t p1 = p0 + ggml_backend_buffer_get_size (tensor->buffer );
1035
1048
1036
1049
if (in_tensor->data + offset < p0 || in_tensor->data + offset >= p1 || size > (p1 - in_tensor->data - offset)) {
1037
- GGML_ABORT (" [%s] tensor->data out of bounds\n " , __func__);
1050
+ // Replace GGML_ABORT with logging and error return
1051
+ GGML_LOG_ERROR (" [%s] tensor data region (data=0x%" PRIx64 " , offset=%" PRIu64 " , size=%zu) out of buffer bounds [0x%zx, 0x%zx)\n " ,
1052
+ __func__, in_tensor->data , offset, size, p0, p1);
1053
+ return false ;
1038
1054
}
1039
1055
}
1040
1056
@@ -1109,7 +1125,11 @@ bool rpc_server::set_tensor_hash(const std::vector<uint8_t> & input, rpc_msg_set
1109
1125
const size_t p1 = p0 + ggml_backend_buffer_get_size (tensor->buffer );
1110
1126
1111
1127
if (in_tensor->data + offset < p0 || in_tensor->data + offset >= p1 || size > (p1 - in_tensor->data - offset)) {
1112
- GGML_ABORT (" [%s] tensor->data out of bounds\n " , __func__);
1128
+ // Replace GGML_ABORT with logging and error return
1129
+ GGML_LOG_ERROR (" [%s] tensor data region (data=0x%" PRIx64 " , offset=%" PRIu64 " , size=%zu, hash=0x%" PRIx64 " ) out of buffer bounds [0x%zx, 0x%zx)\n " ,
1130
+ __func__, in_tensor->data , offset, size, *hash, p0, p1);
1131
+ response.result = 0 ;
1132
+ return false ;
1113
1133
}
1114
1134
}
1115
1135
ggml_backend_tensor_set (tensor, cached_file.data (), offset, size);
@@ -1174,7 +1194,10 @@ bool rpc_server::get_tensor(const rpc_msg_get_tensor_req & request, std::vector<
1174
1194
if (request.tensor .data + request.offset < p0 ||
1175
1195
request.tensor .data + request.offset >= p1 ||
1176
1196
request.size > (p1 - request.tensor .data - request.offset )) {
1177
- GGML_ABORT (" [%s] tensor->data out of bounds\n " , __func__);
1197
+ // Replace GGML_ABORT with logging and error return
1198
+ GGML_LOG_ERROR (" [%s] requested tensor region (data=0x%" PRIx64 " , offset=%" PRIu64 " , size=%" PRIu64 " ) out of buffer bounds [0x%zx, 0x%zx)\n " ,
1199
+ __func__, request.tensor .data , request.offset , request.size , p0, p1);
1200
+ return false ;
1178
1201
}
1179
1202
}
1180
1203
@@ -1197,6 +1220,7 @@ bool rpc_server::copy_tensor(const rpc_msg_copy_tensor_req & request, rpc_msg_co
1197
1220
ggml_tensor * dst = deserialize_tensor(ctx, &request.dst);
1198
1221
if (src == nullptr || dst == nullptr ) {
1199
1222
GGML_LOG_ERROR (" [%s] error deserializing tensors\n " , __func__);
1223
+ response.result = 0 ;
1200
1224
return false ;
1201
1225
}
1202
1226
@@ -1214,6 +1238,7 @@ bool rpc_server::copy_tensor(const rpc_msg_copy_tensor_req & request, rpc_msg_co
1214
1238
dst_data + src_size,
1215
1239
dst_base,
1216
1240
dst_base + dst_buf_sz);
1241
+ response.result = 0 ;
1217
1242
return false ;
1218
1243
}
1219
1244
@@ -1234,43 +1259,118 @@ ggml_tensor * rpc_server::create_node(uint64_t id,
1234
1259
if (tensor_map.find (id) != tensor_map.end ()) {
1235
1260
return tensor_map[id];
1236
1261
}
1237
- const rpc_tensor * tensor = tensor_ptrs.at (id);
1262
+ // Safely find the tensor pointer
1263
+ auto it_ptr = tensor_ptrs.find (id);
1264
+ if (it_ptr == tensor_ptrs.end ()) {
1265
+ GGML_LOG_ERROR (" [%s] tensor id %" PRIu64 " not found in provided tensors\n " , __func__, id);
1266
+ return nullptr ;
1267
+ }
1268
+ const rpc_tensor * tensor = it_ptr->second ;
1269
+
1238
1270
struct ggml_tensor * result = deserialize_tensor (ctx, tensor);
1239
1271
if (result == nullptr ) {
1240
1272
return nullptr ;
1241
1273
}
1242
1274
tensor_map[id] = result;
1243
1275
for (int i = 0 ; i < GGML_MAX_SRC; i++) {
1244
1276
result->src [i] = create_node (tensor->src [i], ctx, tensor_ptrs, tensor_map);
1277
+ // Check if recursive call failed
1278
+ if (tensor->src [i] != 0 && result->src [i] == nullptr ) {
1279
+ GGML_LOG_ERROR (" [%s] failed to create source node %d (src_id=%" PRIu64 " ) for node id %" PRIu64 " \n " ,
1280
+ __func__, i, tensor->src [i], id);
1281
+ // Must return nullptr to signal failure up the call stack
1282
+ return nullptr ;
1283
+ }
1245
1284
}
1246
1285
result->view_src = create_node (tensor->view_src , ctx, tensor_ptrs, tensor_map);
1286
+ // Check if recursive call failed
1287
+ if (tensor->view_src != 0 && result->view_src == nullptr ) {
1288
+ GGML_LOG_ERROR (" [%s] failed to create view_src node (view_src_id=%" PRIu64 " ) for node id %" PRIu64 " \n " ,
1289
+ __func__, tensor->view_src , id);
1290
+ // Must return nullptr to signal failure up the call stack
1291
+ return nullptr ;
1292
+ }
1247
1293
result->view_offs = tensor->view_offs ;
1248
1294
return result;
1249
1295
}
1250
1296
1251
1297
bool rpc_server::graph_compute (const std::vector<uint8_t > & input, rpc_msg_graph_compute_rsp & response) {
1252
1298
// serialization format:
1253
- // | n_nodes (4 bytes) | nodes (n_nodes * sizeof(uint64_t) | n_tensors (4 bytes) | tensors (n_tensors * sizeof(rpc_tensor)) |
1254
- if (input.size () < sizeof (uint32_t )) {
1299
+ // | n_nodes (4 bytes) | nodes (n_nodes * sizeof(uint64_t)) | n_tensors (4 bytes) | tensors (n_tensors * sizeof(rpc_tensor)) |
1300
+
1301
+ // Perform robust size checks with overflow protection
1302
+ const size_t min_header_size = sizeof (uint32_t );
1303
+ if (input.size () < min_header_size) {
1304
+ GGML_LOG_ERROR (" [%s] input message too small for n_nodes header: %zu bytes\n " , __func__, input.size ());
1305
+ response.result = GGML_STATUS_FAILED;
1255
1306
return false ;
1256
1307
}
1257
1308
uint32_t n_nodes;
1258
1309
memcpy (&n_nodes, input.data (), sizeof (n_nodes));
1259
- if (input.size () < sizeof (uint32_t ) + n_nodes*sizeof (uint64_t ) + sizeof (uint32_t )) {
1310
+
1311
+ // Calculate required size for nodes array
1312
+ size_t nodes_array_bytes = n_nodes * sizeof (uint64_t );
1313
+
1314
+ // Calculate required size up to n_tensors field safely
1315
+ size_t required_size_before_tensors = min_header_size;
1316
+
1317
+ // Check for overflow before adding nodes_array_bytes
1318
+ if (SIZE_MAX - required_size_before_tensors < nodes_array_bytes) {
1319
+ GGML_LOG_ERROR (" [%s] integer overflow calculating size before tensors step 1: n_nodes=%u\n " , __func__, n_nodes);
1320
+ response.result = GGML_STATUS_FAILED; // Use correct status
1321
+ return false ;
1322
+ }
1323
+ required_size_before_tensors += nodes_array_bytes;
1324
+
1325
+ const size_t n_tensors_field_size = sizeof (uint32_t );
1326
+ // Check for overflow before adding n_tensors_field_size
1327
+ if (SIZE_MAX - required_size_before_tensors < n_tensors_field_size) {
1328
+ GGML_LOG_ERROR (" [%s] integer overflow calculating size before tensors step 2: n_nodes=%u\n " , __func__, n_nodes);
1329
+ response.result = GGML_STATUS_FAILED; // Use correct status
1260
1330
return false ;
1261
1331
}
1262
- const uint64_t * nodes = (const uint64_t *)(input.data () + sizeof (n_nodes));
1332
+ required_size_before_tensors += n_tensors_field_size;
1333
+
1334
+ if (input.size () < required_size_before_tensors) {
1335
+ GGML_LOG_ERROR (" [%s] input message too small for nodes array or n_tensors header: %zu bytes, needed %zu\n " , __func__, input.size (), required_size_before_tensors);
1336
+ response.result = GGML_STATUS_FAILED; // Use correct status
1337
+ return false ;
1338
+ }
1339
+
1340
+ // Read n_tensors
1341
+ const uint64_t * nodes_ptr = (const uint64_t *)(input.data () + sizeof (n_nodes));
1263
1342
uint32_t n_tensors;
1264
- memcpy (&n_tensors, input.data () + sizeof (n_nodes) + n_nodes*sizeof (uint64_t ), sizeof (n_tensors));
1265
- if (input.size () < sizeof (uint32_t ) + n_nodes*sizeof (uint64_t ) + sizeof (uint32_t ) + n_tensors*sizeof (rpc_tensor)) {
1343
+ memcpy (&n_tensors, input.data () + min_header_size + nodes_array_bytes, sizeof (n_tensors));
1344
+
1345
+ // Calculate required size for tensors array
1346
+ size_t tensors_array_bytes = n_tensors * sizeof (rpc_tensor);
1347
+
1348
+ // Calculate total required size safely
1349
+ size_t required_total_size = required_size_before_tensors;
1350
+
1351
+ // Check for overflow before adding tensors_array_bytes
1352
+ if (SIZE_MAX - required_total_size < tensors_array_bytes) {
1353
+ GGML_LOG_ERROR (" [%s] integer overflow calculating total required size: n_nodes=%u, n_tensors=%u\n " , __func__, n_nodes, n_tensors);
1354
+ response.result = GGML_STATUS_FAILED;
1355
+ return false ;
1356
+ }
1357
+ required_total_size += tensors_array_bytes;
1358
+
1359
+ if (input.size () < required_total_size) {
1360
+ GGML_LOG_ERROR (" [%s] input message too small for tensors array: %zu bytes, needed %zu\n " , __func__, input.size (), required_total_size);
1361
+ response.result = GGML_STATUS_FAILED;
1266
1362
return false ;
1267
1363
}
1268
- const rpc_tensor * tensors = (const rpc_tensor *)(input.data () + sizeof (n_nodes) + n_nodes*sizeof (uint64_t ) + sizeof (n_tensors));
1364
+
1365
+ // Pointers are now safe to use based on size checks
1366
+ const rpc_tensor * tensors = (const rpc_tensor *)(input.data () + required_size_before_tensors);
1269
1367
GGML_PRINT_DEBUG (" [%s] n_nodes: %u, n_tensors: %u\n " , __func__, n_nodes, n_tensors);
1270
1368
1271
- size_t buf_size = ggml_tensor_overhead ()*(n_nodes + n_tensors) + ggml_graph_overhead_custom (n_nodes, false );
1369
+ // Estimate buffer size for context
1370
+ size_t ctx_buf_size = ggml_tensor_overhead ()*((size_t )n_nodes + n_tensors) + ggml_graph_overhead_custom (n_nodes, false );
1371
+
1272
1372
struct ggml_init_params params = {
1273
- /* .mem_size =*/ buf_size ,
1373
+ /* .mem_size =*/ ctx_buf_size ,
1274
1374
/* .mem_buffer =*/ NULL ,
1275
1375
/* .no_alloc =*/ true ,
1276
1376
};
@@ -1286,12 +1386,20 @@ bool rpc_server::graph_compute(const std::vector<uint8_t> & input, rpc_msg_graph
1286
1386
std::unordered_map<uint64_t , ggml_tensor*> tensor_map;
1287
1387
for (uint32_t i = 0 ; i < n_nodes; i++) {
1288
1388
int64_t id;
1289
- memcpy (&id, &nodes [i], sizeof (id));
1389
+ memcpy (&id, &nodes_ptr [i], sizeof (id));
1290
1390
graph->nodes [i] = create_node (id, ctx, tensor_ptrs, tensor_map);
1391
+ // Check if create_node failed (e.g., due to invalid type or missing ID)
1392
+ if (graph->nodes [i] == nullptr ) {
1393
+ GGML_LOG_ERROR (" [%s] failed to create graph node %d (id=%" PRId64 " )\n " , __func__, i, id);
1394
+ response.result = GGML_STATUS_FAILED;
1395
+ // No need to free ctx, ggml_context_ptr handles it.
1396
+ return false ;
1397
+ }
1291
1398
}
1292
1399
ggml_status status = ggml_backend_graph_compute (backend, graph);
1293
1400
response.result = status;
1294
- return true ;
1401
+ // Return true only if computation succeeded
1402
+ return status == GGML_STATUS_SUCCESS;
1295
1403
}
1296
1404
1297
1405
rpc_server::~rpc_server () {
0 commit comments