Buy commercial curl support from WolfSSL. We help you work
out your issues, debug your libcurl applications, use the API, port to new
platforms, add new features and more. With a team lead by the curl founder
himself.
Re: Serialisation problem
- Contemporary messages sorted: [ by date ] [ by thread ] [ by subject ] [ by author ] [ by messages with attachments ]
From: David Chapman via curl-library <curl-library_at_lists.haxx.se>
Date: Thu, 9 Jun 2022 09:42:08 -0700
Looks like a C++ temporary variable lifetime problem. See below.
On 6/9/2022 9:17 AM, J via curl-library wrote:
> Hi,
>
> I'm struggling to understand what the issue might be, but I'm getting
> this error:
>
> {"error-code":"Internal Error","error-message":"JSON parse error:
> Unexpected character ('/' (code 47)): maybe a (non-standard) comment?
> (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for
> parser); nested exception is
> com.fasterxml.jackson.core.JsonParseException: Unexpected character
> ('/' (code 47)): maybe a (non-standard) comment? (not recognized as
> one since Feature 'ALLOW_COMMENTS' not enabled for parser)\n at
> [Source: (PushbackInputStream); line: 1, column: 2]","request-id":""}
>
> When I
> curl_easy_setopt( curl, CURLOPT_POSTFIELDS, s2 );
> But for some reason, the error does not occur when I use
> curl_easy_setopt( curl, CURLOPT_POSTFIELDS, s1 );
> But BOTH strings are nul-terminated and contain the exact same data:
> Contents of string: /(s1)/ 123 34 104 111 115 116 34 58 34 49 57 50 46
> 49 54 56 46 49 57 53 46 49 50 34 125 Contents of string: /(s2)/ 123 34
> 104 111 115 116 34 58 34 49 57 50 46 49 54 56 46 49 57 53 46 49 50 34 125
> What am I not understanding here? The strings are single-byte
> characters, so might it be a problem with some internal
> unicode-conversion?
> Here is the complete code:
> voiddumpstring( constchar*p ) {
> std::cerr <<EOL;
> std::cerr <<"Contents of string:"EOL;
> for( ; *p; p++ ) {
> std::cout <<(int)*p <<" ";
> }
> std::cerr <<EOL;
> }
> boolExecuteCommand( constchar*token, constchar*nodename,
> constchar*command, constchar*tenant, constcmd_params ¶ms ) {
> CURL * curl;
> CURLcode res;
> curl = curl_easy_init();
> if( curl ) {
> curl_easy_setopt( curl, CURLOPT_URL, ( (
> (std::string)"https://ubihub.cityiq-dvp.io/"+tenant
> +"/v1.0/ecs/command/") +nodename +"\?commandId="+command
> +"&mode=sync").c_str() );
Try storing the result of the string appends in a variable. You are
passing a c_str() of a temporary C++ variable and the compiler may
choose to call its destructor before calling curl_easy_setopt().
std::string foo(( (
(std::string)"https://ubihub.cityiq-dvp.io/"+tenant
+"/v1.0/ecs/command/") +nodename +"\?commandId="+command
+"&mode=sync").c_str() );
curl_easy_setopt( curl, CURLOPT_URL, foo.c_str() );
This way the C++ value is guaranteed to have a lifetime longer than the
call to curl_easy_setopt().
You will of course need to do this everywhere; I show only one example.
> curl_easy_setopt( curl, CURLOPT_FOLLOWLOCATION, 1L);
> structcurl_slist *headers = NULL;
> headers = curl_slist_append( headers, ( ( (std::string)"Authorization:
> Bearer ") +token ).c_str() );
> if( params.size() ) {
> headers = curl_slist_append( headers, "Content-Type: application/json");
> Json::StreamWriterBuilder builder;
> builder["indentation"]="";
> Json::Value values;
> for( size_tu = 0; u < params.size(); u++ ) {
> std::size_tequalpos = params.at <http://params.at>( u ).find( "=");
> if( std::string::npos != equalpos ) {
> std::string key = params.at <http://params.at>( u ).substr( 0, equalpos );
> std::string value = params.at <http://params.at>( u ).substr( equalpos
> + 1);
> values[key]=value;
> }
> }
> std::string serialized = Json::writeString( builder, values );
> constchar* s1 = "{\"host\":\"192.168.195.12\"}";
> constchar* s2 = serialized.c_str();
> dumpstring( s1 );
> dumpstring( s2 );
> curl_easy_setopt( curl, CURLOPT_POSTFIELDS, s2 );
> }
> curl_easy_setopt( curl, CURLOPT_HTTPHEADER, headers );
> curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "POST");
> res = curl_easy_perform( curl );
> curl_easy_cleanup( curl );
> if( CURLE_OK!= res ) {
> std::cerr <<"curl_easy_perform() failed: "<<curl_easy_strerror( res )
> <<EOL;
> returnfalse;
> }
> }
> returntrue;
> }
> As I wrote above, both potential strings are dumped at runtime and
> both contain the same characters.
> Any help is appreciated.
> Thanks
>
Date: Thu, 9 Jun 2022 09:42:08 -0700
Looks like a C++ temporary variable lifetime problem. See below.
On 6/9/2022 9:17 AM, J via curl-library wrote:
> Hi,
>
> I'm struggling to understand what the issue might be, but I'm getting
> this error:
>
> {"error-code":"Internal Error","error-message":"JSON parse error:
> Unexpected character ('/' (code 47)): maybe a (non-standard) comment?
> (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for
> parser); nested exception is
> com.fasterxml.jackson.core.JsonParseException: Unexpected character
> ('/' (code 47)): maybe a (non-standard) comment? (not recognized as
> one since Feature 'ALLOW_COMMENTS' not enabled for parser)\n at
> [Source: (PushbackInputStream); line: 1, column: 2]","request-id":""}
>
> When I
> curl_easy_setopt( curl, CURLOPT_POSTFIELDS, s2 );
> But for some reason, the error does not occur when I use
> curl_easy_setopt( curl, CURLOPT_POSTFIELDS, s1 );
> But BOTH strings are nul-terminated and contain the exact same data:
> Contents of string: /(s1)/ 123 34 104 111 115 116 34 58 34 49 57 50 46
> 49 54 56 46 49 57 53 46 49 50 34 125 Contents of string: /(s2)/ 123 34
> 104 111 115 116 34 58 34 49 57 50 46 49 54 56 46 49 57 53 46 49 50 34 125
> What am I not understanding here? The strings are single-byte
> characters, so might it be a problem with some internal
> unicode-conversion?
> Here is the complete code:
> voiddumpstring( constchar*p ) {
> std::cerr <<EOL;
> std::cerr <<"Contents of string:"EOL;
> for( ; *p; p++ ) {
> std::cout <<(int)*p <<" ";
> }
> std::cerr <<EOL;
> }
> boolExecuteCommand( constchar*token, constchar*nodename,
> constchar*command, constchar*tenant, constcmd_params ¶ms ) {
> CURL * curl;
> CURLcode res;
> curl = curl_easy_init();
> if( curl ) {
> curl_easy_setopt( curl, CURLOPT_URL, ( (
> (std::string)"https://ubihub.cityiq-dvp.io/"+tenant
> +"/v1.0/ecs/command/") +nodename +"\?commandId="+command
> +"&mode=sync").c_str() );
Try storing the result of the string appends in a variable. You are
passing a c_str() of a temporary C++ variable and the compiler may
choose to call its destructor before calling curl_easy_setopt().
std::string foo(( (
(std::string)"https://ubihub.cityiq-dvp.io/"+tenant
+"/v1.0/ecs/command/") +nodename +"\?commandId="+command
+"&mode=sync").c_str() );
curl_easy_setopt( curl, CURLOPT_URL, foo.c_str() );
This way the C++ value is guaranteed to have a lifetime longer than the
call to curl_easy_setopt().
You will of course need to do this everywhere; I show only one example.
> curl_easy_setopt( curl, CURLOPT_FOLLOWLOCATION, 1L);
> structcurl_slist *headers = NULL;
> headers = curl_slist_append( headers, ( ( (std::string)"Authorization:
> Bearer ") +token ).c_str() );
> if( params.size() ) {
> headers = curl_slist_append( headers, "Content-Type: application/json");
> Json::StreamWriterBuilder builder;
> builder["indentation"]="";
> Json::Value values;
> for( size_tu = 0; u < params.size(); u++ ) {
> std::size_tequalpos = params.at <http://params.at>( u ).find( "=");
> if( std::string::npos != equalpos ) {
> std::string key = params.at <http://params.at>( u ).substr( 0, equalpos );
> std::string value = params.at <http://params.at>( u ).substr( equalpos
> + 1);
> values[key]=value;
> }
> }
> std::string serialized = Json::writeString( builder, values );
> constchar* s1 = "{\"host\":\"192.168.195.12\"}";
> constchar* s2 = serialized.c_str();
> dumpstring( s1 );
> dumpstring( s2 );
> curl_easy_setopt( curl, CURLOPT_POSTFIELDS, s2 );
> }
> curl_easy_setopt( curl, CURLOPT_HTTPHEADER, headers );
> curl_easy_setopt( curl, CURLOPT_CUSTOMREQUEST, "POST");
> res = curl_easy_perform( curl );
> curl_easy_cleanup( curl );
> if( CURLE_OK!= res ) {
> std::cerr <<"curl_easy_perform() failed: "<<curl_easy_strerror( res )
> <<EOL;
> returnfalse;
> }
> }
> returntrue;
> }
> As I wrote above, both potential strings are dumped at runtime and
> both contain the same characters.
> Any help is appreciated.
> Thanks
>
-- David Chapmandcchapman_at_acm.org Chapman Consulting -- San Jose, CA EDA Software Developer, Expert Witness www.chapman-consulting-sj.com 2018-2019 Chair, IEEE Consultants' Network of Silicon Valley
-- Unsubscribe: https://lists.haxx.se/listinfo/curl-library Etiquette: https://curl.haxx.se/mail/etiquette.htmlReceived on 2022-06-09