0

I created a simple scriptable npapi plugin. It works fine to pass string between JavaScript and plugin on FireFox. But it will generate some extra random characters on Google chrome if the string contains hyphen (-) symbol. For example, in my JavaScript code, I have

plugin.method("a-b");

on my npapi code, I have

bool ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) {

  char* outString = args[0].value.stringValue.UTF8Characters;
  char* npOutString = (char *)NPN_MemAlloc(strlen(outString) + 1);
  strcpy(npOutString, outString);
  STRINGZ_TO_NPVARIANT(npOutString, *result);

  return true;
}

On Firefox, it returns "a-b", on Chrome, I will see "a-b*[-.." with some extra random symbols. I tried with placing npplugin.dll in "plugins" directory under Mozilla or using Chrome extension tutorial(http://code.google.com/chrome/extensions/npapi.html), both way gave me the same strange behavior. The code is compiled with xulrunner-10.0.2.en-US.win32.sdk, using xulrunner-1.9.0.17.en-US.win32.sdk also has the same problem.

Does anyone have any clues?

Dino Tw
  • 3,167
  • 4
  • 34
  • 48

1 Answers1

2

Your problem is that you are assuming that it is a standard NULL terminated C string. In practice, NPAPI strings often are C strings and NULL terminated but there is no guarantee that this will be the case. If you look at the npruntime.h header file from the npapi-sdk project you'll see that there is a UTF8Length member of NPString; this isn't just for decoration. You should always be using that to determine the length (in bytes) of the UTF8 string.

To reiterate what smorgan said in the comment below, this means that you cannot use strcpy, strlen, or any other C string function for accessing it; an NPString is a byte+length pair, so you need to access it using byte+length methods.

For example:

bool ScriptablePluginObject::Invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) {

  char* outString = args[0].value.stringValue.UTF8Characters;
  int outLen = args[0].value.stringValue.UTF8Length;
  char* npOutString = (char *)NPN_MemAlloc(outLen + 1);
  memcpy(npOutString, outString, outLen);
  // Make this NULL terminated
  npOutString[outLen] = NULL;
  STRINGZ_TO_NPVARIANT(npOutString, *result);

  return true;
}

Note that you should also be checking to make sure that the NPVariant is actually a string or this could all easily blow up in your face.

taxilian
  • 14,229
  • 4
  • 34
  • 73
  • Yes, I am aware of NPString property, UTF8Length. When I tried to return the string length, the value was correct. So I also tried to set the string length manually, the type of strange behavior still happened. In my example, I tried NPN_MemAlloc(3) and NPN_MemAlloc(4) for input string "a-b". The issue only happens when there is a hyphen in the string. If the input string is simply "abc", it works correctly on both FF and Chrome. – Dino Tw Jun 08 '12 at 04:41
  • 2
    You're missing the point; the string-handling functions you are using (strlen, strcpy) are designed to operate on NULL-terminated strings. You don't have a NULL-terminated string, you have a byte+length pair. You cannot use methods designed to operate on NULL-terminated strings on NPStrings. When it's working for you, it's by accident. You should be using UTF8Length instead of strlen(), and you should be using memcpy with a length and then NULL-terminating the result yourself. (When you forced shorter values in NPN_MemAlloc all you did is create a buffer overrun in your strcpy.) – smorgan Jun 08 '12 at 10:08
  • Thank you for the great help from taxilian and smorgan, the code now works as expected. I did not know the trick before, and I will keep it in mind when doing the NPAPI development. Again, thank you so much. – Dino Tw Jun 08 '12 at 18:02