Native-messaging API appears to ignore JSON strings of size equal to multiples of 256 plus 10?

I’ve substantially edited this question from the original now that have more information and to make it shorter and more clear. The code in C and in the background script are provided at the end.

When the C code passes a JSON string to the extension background script, prefixing the four-byte uint32 string size, all appears to work fine and the message is received and parsed. If the message is badly formed JSON, the parse fails before reaching the BS code and errors in subprocess_common.jsm:493, closing the C application. If the prefix is absent, then most of the time the BS errors stating that the size is too large. That’s all fine.

However, whenever the string size is a multiple of 256 + 10 bytes, the BS behaves as if the string was never sent. I’ve tested sizes 266 and 522 bytes and both fail; but simply adding or removing one byte from the string results in success. By fails I mean that it does nothing, as if the message was never sent; the connection is not closed and no errors are thrown.

Testing the C code on the command line with the exact same input sent from the BS, results in the correct response being printed to stdout/the screen. Thus, it appears that the C code is working fine, especially since it works fine for other JSON string sizes.

The JSON responses are also written to a local file to assist in debugging, and the ones of size 266 and 522 have the JSON on the next line from the four bytes indicating size, while all others appear on the same line.

I think the idea, as pointed out to me for I don’t know enough to have thought of it, is that 266 is 10 larger than 256 and 522 is 10 larger than 2*256, which makes the first character of the size prefix 10 in both cases and which is equivalent to \n.

I don’t know much about about bytes and bits, but do know a little about math and understand that it takes eight places in binary numbers to represent the value 255; and I think there are eight bits in a byte. I don’t know what is special about ten in a byte except that it appears to perhaps be represented by a new line character. When run on the command line and printed to the screen, a smiley face is printed for these sizes.

I don’t know if this takes place in other browsers because I don’t code extensions for other browsers.

If you happen to know what might be going on in the JSON parser or if you can receive a JSON string of 266 or 522 bytes in the native-messaging API, I’d appreciate knowing.

I should perhaps add that I can add code in C to test whether or not the string size is a multiple of 256 + 10 and, when true, add an unnecessary property to the string, such as "p":0 simply to alter the size; however, I’d like to know why and whether or not other sizes cause a similar issue. Is it my C code or the native-messaging API or my OS, etcetera. I’m using Windows for this current version.

Thank you.


I believe the answer is that found at the Chrome page I referenced a few edits ago. Here is the link and it is the last bullet there. Take that link to _setmode() and set stdout to _O_BINARY and it will likely work. At least, it solved it for me.

result = _setmode( _fileno( stdout ), _O_BINARY );

I tried it last night, and it worked for stdin but I couldn’t get it to work for stdout. Since I was getting nowhere and was told again that the issue is likely related to Windows carriage return /r/n instead of Unix /n, I tried it again. Most likely, when I added in the stdout code last night I did something stupid like typing an _0_BINARY instead of an _O_BINARY. Idiot! But at least it works now.

int send_response( const char *response )
  {
    int rc;
    FILE *fp_out;
    fp_out = fopen( "test.txt", "w" );

    // Write response ( JSON prefixed with its UTF-8 length ).
    const uint32_t len = strlen( response );

    if ( ( rc = fwrite( &len, sizeof len, 1, fp_out ) ) != 1 ||
         ( rc = fwrite( response, len, 1, fp_out ) ) != 1 )
    {}

    if ( ( rc = fwrite( &len, sizeof len, 1, stdout ) ) != 1 ||
         ( rc = fwrite( response, sizeof *response, len, stdout ) ) != len )
      {
        perror( "fwrite" );
        return EXIT_FAILURE;
      }

    fclose( fp_out );
    return 0;

  } // close send_response
  function nativeApp( o, p )
    {
      try
        {
          // Establish connection with native application.
          nativeApp.port = browser.runtime.connectNative( "AppName" );
          console.log( nativeApp.port );

          // Listen for messages from the app.
          nativeApp.port.onMessage.addListener( ( response ) =>
            {
              try
                {
                  console.log( "Received response at extension:" );
                  console.log( response );
                  if ( 'c' in response ) 
                    nativeApp.settle_promise( response );
                  else 
                    console.log( "Not yet coded to do anything else with response." );
                }
              catch ( e )
                {
                  console.log( "Error receiving message:");
                  console.log( e );
                }     
            });

          nativeApp.port.onDisconnect.addListener( ( p ) =>
            {
              console.log( p );
              if ( p.error )
                {
                  console.log( `Disconnected due to an error: ${ p.error.message }` );
                }
            } );
        }
      catch ( e )
        {
          console.log( "Error in nativeApp; reason below." );
          console.log( e );
        }  
    } // close nativeApp