Skip to content

Commit e793a58

Browse files
committed
avoid adding zero sized buffer to TRITONSERVER_InferenceRequestAddInput
1 parent dcac291 commit e793a58

3 files changed

Lines changed: 37 additions & 19 deletions

File tree

qa/L0_http/http_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/python
2-
# Copyright 2022-2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# Copyright 2022-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
33
#
44
# Redistribution and use in source and binary forms, with or without
55
# modification, are permitted provided that the following conditions

qa/L0_http/test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ wait $SERVER_PID
655655
# https://github.com/mpetazzoni/sseclient
656656
pip install sseclient-py
657657

658-
SERVER_ARGS="--model-repository=`pwd`/../python_models/generate_models"
658+
SERVER_ARGS="--model-repository=`pwd`/../python_models/generate_models --log-verbose=1"
659659
SERVER_LOG="./inference_server_generate_endpoint_test.log"
660660
CLIENT_LOG="./generate_endpoint_test.log"
661661
run_server

src/http_server.cc

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ ReadDataFromJsonHelper(
481481
if (!base) {
482482
return TRITONSERVER_ErrorNew(
483483
TRITONSERVER_ERROR_INTERNAL,
484-
"output buffer `base` pointer cannot be null");
484+
"Failed to parse 'data' field: output buffer unavailable");
485485
}
486486
// FIXME should move 'switch' statement outside the recursive function and
487487
// pass in a read data callback once data type is confirmed.
@@ -508,13 +508,14 @@ ReadDataFromJsonHelper(
508508
} else {
509509
if (!counter) {
510510
return TRITONSERVER_ErrorNew(
511-
TRITONSERVER_ERROR_INTERNAL, "`counter` pointer cannot be null");
511+
TRITONSERVER_ERROR_INTERNAL,
512+
"Failed to parse 'data' field: invalid counter provided");
512513
}
513514
// Check if writing to 'serialized' is overrunning the expected byte_size
514515
if (*counter < 0 || static_cast<int64_t>(*counter) >= expected_cnt) {
515516
return TRITONSERVER_ErrorNew(
516517
TRITONSERVER_ERROR_INTERNAL,
517-
"Shape does not match true shape of 'data' field");
518+
"Failed to parse 'data' field: shape does not match true shape");
518519
}
519520
switch (dtype) {
520521
case TRITONSERVER_TYPE_BOOL: {
@@ -618,7 +619,8 @@ ReadDataFromJsonHelper(
618619
if (len > INT64_MAX) {
619620
return TRITONSERVER_ErrorNew(
620621
TRITONSERVER_ERROR_INTERNAL,
621-
"Tensor size is too large to be processed");
622+
"Failed to parse 'data' field: tensor size is too large to be "
623+
"processed");
622624
}
623625
// Quick sanity check to ensure we don't write beyond `expected_cnt`.
624626
int64_t actual_cnt = static_cast<int64_t>(*counter) +
@@ -627,7 +629,7 @@ ReadDataFromJsonHelper(
627629
if (actual_cnt < 0 || actual_cnt > expected_cnt) {
628630
return TRITONSERVER_ErrorNew(
629631
TRITONSERVER_ERROR_INTERNAL,
630-
"Shape does not match true shape of 'data' field");
632+
"Failed to parse 'data' field: shape does not match true shape");
631633
}
632634
memcpy(
633635
base + *counter, reinterpret_cast<char*>(&len), sizeof(uint32_t));
@@ -677,6 +679,11 @@ ReadDataFromJson(
677679
.c_str());
678680

679681
default:
682+
if (!base) {
683+
return TRITONSERVER_ErrorNew(
684+
TRITONSERVER_ERROR_INTERNAL,
685+
"Failed to parse 'data' field: output buffer unavailable");
686+
}
680687
RETURN_MSG_IF_ERR(
681688
ReadDataFromJsonHelper(
682689
base, dtype, tensor_data, &counter, expected_cnt),
@@ -688,8 +695,7 @@ ReadDataFromJson(
688695
if (counter != expected_cnt) {
689696
return TRITONSERVER_ErrorNew(
690697
TRITONSERVER_ERROR_INTERNAL,
691-
"Unable to parse 'data': Shape does not match true shape of 'data' "
692-
"field");
698+
"Failed to parse 'data' field: shape does not match true shape");
693699
}
694700

695701
return nullptr;
@@ -704,7 +710,8 @@ WriteDataToJsonCheck(
704710
return TRITONSERVER_ErrorNew(
705711
TRITONSERVER_ERROR_INTERNAL,
706712
std::string(
707-
"output tensor shape does not match size of output for '" +
713+
"Failed to write 'data' field: output tensor shape does not match "
714+
"size of output for '" +
708715
output_name + "'")
709716
.c_str());
710717
}
@@ -725,7 +732,8 @@ WriteDataToJson(
725732
return TRITONSERVER_ErrorNew(
726733
TRITONSERVER_ERROR_INTERNAL,
727734
std::string(
728-
"output tensor shape does not match size of output for '" +
735+
"Failed to write 'data' field: output tensor shape does not "
736+
"match size of output for '" +
729737
output_name + "'")
730738
.c_str());
731739
}
@@ -2694,12 +2702,12 @@ HTTPAPIServer::ParseJsonTritonIO(
26942702
infer_req->serialized_data_.emplace_back();
26952703
std::vector<char>& serialized = infer_req->serialized_data_.back();
26962704
serialized.resize(byte_size);
2697-
2705+
char* serialized_base = &serialized[0];
26982706
RETURN_IF_ERR(ReadDataFromJson(
2699-
input_name, tensor_data, &serialized[0], dtype,
2707+
input_name, tensor_data, serialized_base, dtype,
27002708
dtype == TRITONSERVER_TYPE_BYTES ? byte_size : element_cnt));
27012709
RETURN_IF_ERR(TRITONSERVER_InferenceRequestAppendInputData(
2702-
irequest, input_name, &serialized[0], serialized.size(),
2710+
irequest, input_name, serialized_base, serialized.size(),
27032711
TRITONSERVER_MEMORY_CPU, 0 /* memory_type_id */));
27042712
}
27052713
}
@@ -3602,9 +3610,9 @@ HTTPAPIServer::GenerateRequestClass::ExactMappingInput(
36023610
.c_str());
36033611
}
36043612

3613+
size_t byte_size{0};
36053614
size_t element_cnt = tensor_data.IsArray() ? tensor_data.ArraySize() : 1;
36063615

3607-
size_t byte_size = 0;
36083616
if (dtype == TRITONSERVER_TYPE_BYTES) {
36093617
RETURN_IF_ERR(JsonBytesArrayByteSize(tensor_data, &byte_size));
36103618
} else {
@@ -3625,9 +3633,17 @@ HTTPAPIServer::GenerateRequestClass::ExactMappingInput(
36253633
(std::string("input '") + name +
36263634
"' has too many elements of datatype " + value)
36273635
.c_str());
3628-
3629-
byte_size = element_cnt * element_size;
36303636
}
3637+
3638+
byte_size = element_cnt * element_size;
3639+
}
3640+
3641+
if (byte_size == 0) {
3642+
// For zero-size input, we can skip the rest of the validation and just
3643+
// add it as an empty input.
3644+
RETURN_IF_ERR(TRITONSERVER_InferenceRequestAddInput(
3645+
triton_request_.get(), name.c_str(), dtype, nullptr, 0));
3646+
return nullptr;
36313647
}
36323648

36333649
// Ensure that the resulting array size in bytes does not exceed the maximum
@@ -3700,15 +3716,17 @@ HTTPAPIServer::GenerateRequestClass::ExactMappingInput(
37003716
serialized_data_.emplace_back();
37013717
std::vector<char>& serialized = serialized_data_.back();
37023718
serialized.resize(byte_size);
3719+
char* serialized_base = &serialized[0];
3720+
37033721
RETURN_IF_ERR(ReadDataFromJson(
3704-
name.c_str(), tensor_data, &serialized[0], dtype,
3722+
name.c_str(), tensor_data, serialized_base, dtype,
37053723
dtype == TRITONSERVER_TYPE_BYTES ? byte_size : element_cnt));
37063724

37073725
RETURN_IF_ERR(TRITONSERVER_InferenceRequestAddInput(
37083726
triton_request_.get(), name.c_str(), dtype, &shape_vec[0],
37093727
shape_vec.size()));
37103728
RETURN_IF_ERR(TRITONSERVER_InferenceRequestAppendInputData(
3711-
triton_request_.get(), name.c_str(), &serialized[0], serialized.size(),
3729+
triton_request_.get(), name.c_str(), serialized_base, serialized.size(),
37123730
TRITONSERVER_MEMORY_CPU, 0 /* memory_type_id */));
37133731
}
37143732
return nullptr; // success

0 commit comments

Comments
 (0)