0
votes

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?

1

1 Answers

2
votes

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.