0

I'm using cJSON in combination with the JNI to pass JSON data back and forth between my Java and C components.

I'm new to C and teaching myself, so bear with me.

cJSON has a nice function, cJSON->Print, which converts a JSON structure into a string representation. This is great, except the string is in "JSON Pretty" format, with all the newlines and tab characters intact. I don't need any of those because my application doesn't display JSON, it just uses it for data transfer. So, I'm trying to write a function that will remove those excess characters.

void json_clean(char *buffer, const char *pretty) {
    int count = 0;
    for(int i = 0; i < strlen(pretty); i++) {
        if(pretty[i] == '\n' || pretty[i] == '\t')
            continue;

        buffer[count] = pretty[i];
        count++;
    }

    int last = strlen(buffer) - 1;
    buffer[last] = '\0';
}

This effectively removes the \n and \t characters just fine, but sometimes at the end I get some trash characters, like 6 or ?, which leads me to think this is a null-termination issue.

The string comes out the same way when using printf in C and printing it out in Java.

I make sure to allocate one more byte than I need for the NUL character before I call the function:

// get the pretty JSON
const char *pretty = cJSON_Print(out);

// how many newlines and tabs?
int count = 0;
for(int i = 0; i < strlen(pretty); i++) {
    if(pretty[i] == '\n' || pretty[i] == '\t')
        count++;
}

// make new buffer, excluding these chars
char *newBuf = malloc((strlen(pretty) - count) + 1); // +1 for null term.
json_clean(newBuf, pretty);

// copy into new Java string
jstring retVal = (*env)->NewStringUTF(env, newBuf);
free(newBuf); // don't need this anymore

Any help is greatly appreciated.

Sled
  • 18,541
  • 27
  • 119
  • 168
David Mordigal
  • 813
  • 2
  • 9
  • 22
  • To add to @xing's comment, the problem is that `newBuf` is not initialized, so the `strlen` call is reading random data and walking off into area's it shouldn't. If you zeroed the memory before using it you would be fine, but again, @xing's response is the better solution. – DocMax Oct 15 '17 at 22:17

1 Answers1

0

The solution was to set the null character's index manually, rather than relying on strlen to figure out the last index (which only looks for a null character). If there is no null character in the buffer, strlen does not yield a useful result.

buffer[count] = '\0';

David Mordigal
  • 813
  • 2
  • 9
  • 22
  • "`strlen` will return the actual allocated length of the buffer" -- that is incorrect. `strlen` will find the index of the first nul byte. If you don't have a nul byte in the buffer, `strlen` will happily overrun the end of the buffer. – Dietrich Epp Oct 22 '17 at 03:20