Skip to content

Commit 5b99c6e

Browse files
committed
[http] strictly check arguments in ProduceExe
Always use DecodeUrlOptionValue method when processing URL arguments or URL string. Internally method provides escape symbols for quotes and backslash. If expecting numeric value - remove all symbols keeping alphanumeric, '.', '+', '-' and ':'
1 parent 0433163 commit 5b99c6e

1 file changed

Lines changed: 61 additions & 40 deletions

File tree

net/httpsniff/src/TRootSnifferFull.cxx

Lines changed: 61 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -625,47 +625,46 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
625625
return debug != nullptr;
626626
const char *rest_url = pos + strlen(method_name) + 7;
627627
if (*rest_url == '&') ++rest_url;
628-
call_args.Form("\"%s\"", rest_url);
628+
call_args.Append("\"");
629+
call_args.Append(DecodeUrlOptionValue(rest_url, kTRUE));
630+
call_args.Append("\"");
629631
break;
630632
}
631633

632634
TString sval;
633635
const char *val = url.GetValueFromOptions(arg->GetName());
634-
if (val) {
635-
sval = DecodeUrlOptionValue(val, kFALSE);
636-
val = sval.Data();
637-
}
636+
if (val)
637+
sval = DecodeUrlOptionValue(val, kTRUE);
638+
639+
Bool_t sanitize_numeric = kFALSE;
638640

639-
if ((val != nullptr) && (strcmp(val, "_this_") == 0)) {
641+
if (sval == "_this_") {
640642
// special case - object itself is used as argument
641643
sval.Form("(%s*)0x%zx", obj_cl->GetName(), (size_t)obj_ptr);
642-
val = sval.Data();
643-
} else if ((val != nullptr) && (fCurrentArg != nullptr) && (fCurrentArg->GetPostData() != nullptr)) {
644+
} else if ((fCurrentArg != nullptr) && (fCurrentArg->GetPostData() != nullptr)) {
644645
// process several arguments which are specific for post requests
645-
if (strcmp(val, "_post_object_xml_") == 0) {
646+
if (sval == "_post_object_xml_") {
646647
// post data has extra 0 at the end and can be used as null-terminated string
647648
post_obj = TBufferXML::ConvertFromXML((const char *)fCurrentArg->GetPostData());
648-
if (!post_obj) {
649+
if (!post_obj)
649650
sval = "0";
650-
} else {
651+
else {
651652
sval.Form("(%s*)0x%zx", post_obj->ClassName(), (size_t)post_obj);
652653
if (url.HasOption("_destroy_post_"))
653654
garbage.Add(post_obj);
654655
}
655-
val = sval.Data();
656-
} else if (strcmp(val, "_post_object_json_") == 0) {
656+
} else if (sval == "_post_object_json_") {
657657
// post data has extra 0 at the end and can be used as null-terminated string
658658
post_obj = TBufferJSON::ConvertFromJSON((const char *)fCurrentArg->GetPostData());
659-
if (!post_obj) {
659+
if (!post_obj)
660660
sval = "0";
661-
} else {
661+
else {
662662
sval.Form("(%s*)0x%zx", post_obj->ClassName(), (size_t)post_obj);
663663
if (url.HasOption("_destroy_post_"))
664664
garbage.Add(post_obj);
665665
}
666-
val = sval.Data();
667-
} else if ((strcmp(val, "_post_object_") == 0) && url.HasOption("_post_class_")) {
668-
TString clname = url.GetValueFromOptions("_post_class_");
666+
} else if ((sval == "_post_object_") && url.HasOption("_post_class_")) {
667+
TString clname = DecodeUrlOptionValue(url.GetValueFromOptions("_post_class_"), kTRUE);
669668
TClass *arg_cl = gROOT->GetClass(clname, kTRUE, kTRUE);
670669
if ((arg_cl != nullptr) && (arg_cl->GetBaseClassOffset(TObject::Class()) == 0) && (post_obj == nullptr)) {
671670
post_obj = (TObject *)arg_cl->New();
@@ -682,39 +681,61 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
682681
garbage.Add(post_obj);
683682
}
684683
}
685-
sval.Form("(%s*)0x%zx", clname.Data(), (size_t)post_obj);
686-
val = sval.Data();
687-
} else if (strcmp(val, "_post_data_") == 0) {
684+
if (!post_obj)
685+
sval = "0";
686+
else
687+
sval.Form("(%s*)0x%zx", clname.Data(), (size_t)post_obj);
688+
} else if (sval == "_post_data_")
688689
sval.Form("(void*)0x%zx", (size_t)fCurrentArg->GetPostData());
689-
val = sval.Data();
690-
} else if (strcmp(val, "_post_length_") == 0) {
690+
else if (sval == "_post_length_")
691691
sval.Form("%ld", (long)fCurrentArg->GetPostDataLength());
692-
val = sval.Data();
693-
}
694-
}
692+
else
693+
sanitize_numeric = kTRUE;
694+
} else
695+
sanitize_numeric = kTRUE;
695696

696-
if (!val)
697-
val = arg->GetDefault();
697+
if (sval.IsNull() && arg->GetDefault())
698+
sval = arg->GetDefault();
698699

699700
if (debug)
700-
debug->append(TString::Format(" Argument:%s Type:%s Value:%s \n", arg->GetName(), arg->GetFullTypeName(),
701-
val ? val : "<missed>")
702-
.Data());
703-
if (!val)
704-
return debug != nullptr;
701+
debug->append(
702+
TString::Format(" Argument:%s Type:%s Value:%s \n", arg->GetName(), arg->GetFullTypeName(), sval.Data())
703+
.Data());
705704

706705
if (call_args.Length() > 0)
707706
call_args += ", ";
708707

709-
if ((strcmp(arg->GetFullTypeName(), "const char*") == 0) || (strcmp(arg->GetFullTypeName(), "Option_t*") == 0)) {
710-
int len = strlen(val);
711-
if ((strlen(val) < 2) || (*val != '\"') || (val[len - 1] != '\"'))
712-
call_args.Append(TString::Format("\"%s\"", val));
713-
else
714-
call_args.Append(val);
708+
Bool_t isstr = (strcmp(arg->GetFullTypeName(), "const char*") == 0) ||
709+
(strcmp(arg->GetFullTypeName(), "Option_t*") == 0) ||
710+
(strcmp(arg->GetFullTypeName(), "string") == 0);
711+
712+
if (isstr) {
713+
// check that quotes provided for the string argument
714+
// all special characters were escaped before
715+
if (sval.IsNull())
716+
sval = "\"\"";
717+
else {
718+
if (sval[0] != '"')
719+
sval.Prepend("\"");
720+
if (sval[sval.Length() - 1] != '"')
721+
sval.Append("\"");
722+
}
715723
} else {
716-
call_args.Append(val);
724+
// for numeric types keep only numeric and alphabetic characters
725+
// exclude others - especially remove all escape characters
726+
if (sanitize_numeric) {
727+
TString sanitized;
728+
for(Size_t i = 0; i < sval.Length(); ++i) {
729+
if (std::isalnum(sval[i]) || std::strchr(".:+-", sval[i]))
730+
sanitized.Append(sval[i]);
731+
}
732+
sval = sanitized;
733+
}
734+
if (sval.IsNull())
735+
sval = "0";
717736
}
737+
738+
call_args.Append(sval);
718739
}
719740

720741
TMethodCall *call = nullptr;

0 commit comments

Comments
 (0)