Get different results while running v8 javascript engine on Mac OSX(10.10, 64bit) and CentOS7(64bit)

42 views
Skip to first unread message

solar

unread,
Jun 11, 2015, 11:47:27 PM6/11/15
to v8-u...@googlegroups.com

I am new to v8, and I am using the following c++ code to call a javascript function and get the return value of the js function.

char* worker_run(worker* w, char* name_s, char* source_s) {
  Locker locker(w->isolate);
  Isolate::Scope isolate_scope(w->isolate);
  HandleScope handle_scope(w->isolate);

  Local<Context> context = Local<Context>::New(w->isolate, w->context);
  Context::Scope context_scope(context);

  TryCatch try_catch;

  Local<String> name = String::NewFromUtf8(w->isolate, name_s);
  Local<String> source = String::NewFromUtf8(w->isolate, source_s);

  ScriptOrigin origin(name);

  Local<Script> script = Script::Compile(source, &origin);
  if (script.IsEmpty()) {
    assert(try_catch.HasCaught());
    w->last_exception = ExceptionString(w->isolate, &try_catch);
    return NULL;
  }

  Handle<Value> result = script->Run();
  if (result.IsEmpty()) {
    assert(try_catch.HasCaught());
    w->last_exception = ExceptionString(w->isolate, &try_catch);
    printf("run errrrrr \n");
    return NULL;
  }

  char* retval = (char*)ToCString(String::Utf8Value(result));
  printf("retval = %s, %p \n", retval, retval);
  print_buff((const unsigned char*)retval, 100);
  if (retval == NULL) {
    w->last_exception = "retval from javascript is NULL";
    return NULL;
  }

  int retlen = strlen(retval);
  if (retlen > 0) {
    char* retbuff = (char*)malloc(retlen + 1);
    strcpy(retbuff, retval);

    return retbuff;
  }

  return NULL;
}

the js function as below

function enter(msg) {
    $print('js  ' + msg);   
    return 'zmzmzmzm';
}

enter('aaa');

the expected result is that the pointer "retval" should be the return value of the js function, however, on Mac OSX, it worked fine, on CentOS , "retval" was not NULL but pointed a memory address which has a series of '\0'.

It's weird, so I added a print function to show the first 100 bytes content of the pointer "retval", and the result as below

on Mac OSX

retval = zmzmzmzm, 0x4f00b70 
7A 6D 7A 6D 7A 6D 7A 6D  00 3D 20 73 73 73 73 00  zmzmzmzm  .=.ssss.
00 00 00 00 00 00 00 00  0C 01 4F 00 00 00 00 40  ........  ..O....@
51 00 65 41 6C 6C 6F 63  61 74 69 6F 6E 4D 65 6D  Q.eAlloc  ationMem
65 6E 74 6F 73 3A 53 74  72 69 6E 67 2A 53 74 72  entos:St  ring*Str
69 6E 67 2D 3E 53 74 72  69 6E 67 29 00 00 00 00  ing->Str  ing)....
B0 78 01 06 00 00 00 00  00 00 00 00 00 00 00 00  .x......  ........
F0 0B F0 04

On CentOS7

retval = , 0x2aff210 
00 00 00 00 00 00 00 00  00 3D 20 73 73 73 73 00  ........  .=.ssss.
20 00 00 00 00 00 00 00  21 00 00 00 00 00 00 00  ........  !.......
06 00 00 00 02 00 00 00  00 00 00 00 58 7F 00 00  ........  ....X...
20 00 00 00 00 00 00 00  51 08 00 00 00 00 00 00  ........  Q.......
B8 EC BD D6 58 7F 00 00  B8 EC BD D6 58 7F 00 00  ....X...  ....X...
40 F2 AF 02 00 00 00 00  40 F2 AF 02 00 00 00 00  @.......  @.......
40 D1 AF 02 

I am very confused about this result, the version of v8 I am using is 4.3.59. I also tried the nearest version 4.5.9, the problem still exists.

I had no idea about this, I just tried a longer return value from js

js code

function enter(msg) {
    $print('js  ' + msg);   
    return 'AAAABBBBCCCCDDDD';
}

enter('aaa');

the results  as below

on Mac OSX

retval = AAAABBBBCCCCDDDD, 0x4e08470 
41 41 41 41 42 42 42 42  43 43 43 43 44 44 44 44  AAAABBBB  CCCCDDDD
00 00 03 05 00 00 00 00  89 E4 52 3D 67 28 00 00  ........  ..R=g(..
00 00 00 00 00 00 00 00  FC 05 4E 00 00 00 00 30  ........  ..N....0
A1 10 57 3D 67 28 00 00  A1 10 57 3D 67 28 00 00  ..W=g(..  ..W=g(..
02 00 03 05 00 00 00 00  71 6D 31 CC 6B 01 02 00  ........  qm1.k...
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ........  ........
A9 00 3A A4

On CentOS7

retval = , 0x1e89d00 
00 00 00 00 00 00 00 00  43 43 43 43 44 44 44 44  ........  CCCCDDDD
00 17 E9 01 00 00 00 00  31 00 00 00 00 00 00 00  ........  1.......
D8 67 8E DA 39 7F 00 00  D8 67 8E DA 39 7F 00 00  .g..9...  .g..9...
D0 12 9B 00 00 00 00 00  06 46 AF 00 00 00 00 00  ........  .F......
30 00 00 00 00 00 00 00  20 00 00 00 00 00 00 00  0.......  ........
A1 10 C7 19 15 29 00 00  A1 10 C7 19 15 29 00 00  .....)..  .....)..
00 00 00 00 


From the result, it seems that the first 8 bytes has been overwritten by v8 on CentOS. There might be a out-of-bound  memory access here


BTW, I tried this on Ubuntu14, the result was the same as CentOS7


Need Help! thank you

Sven Panne

unread,
Jun 12, 2015, 3:21:38 AM6/12/15
to v8-u...@googlegroups.com
On Fri, Jun 12, 2015 at 5:47 AM, solar <solarc...@gmail.com> wrote:
[...]

  char* retval = (char*)ToCString(String::Utf8Value(result));
  printf("retval = %s, %p \n", retval, retval);

That's a classical use-after-free bug: String::Utf8Value(result) results in a temporary object which is dead after the first line, see http://en.cppreference.com/w/cpp/language/lifetime#Temporary_object_lifetime. String::Utf8Value's destructor frees the underlying buffer, so retval always points to dead memory. Depending on your compiler/runtime/etc. anything can happen when you use that. Hint: Use e.g. valgrind/ASAN/... or other memory debuggers to easily find such bugs.

Laurel BC

unread,
Jun 12, 2015, 4:30:19 AM6/12/15
to v8-u...@googlegroups.com
Thank you for you comments,  problem resolved. 

I divided this line into two lines
char* retval = (char*)ToCString(String::Utf8Value(result));
=============>
  String::Utf8Value retv(result);
  char* retval = (char*)ToCString(retv);
Just create an explicit object of String::Utf8Value, then I can use it and it will not be destroyed automatically before the function returns.







--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to a topic in the Google Groups "v8-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/v8-users/kwTLzUerG4o/unsubscribe.
To unsubscribe from this group and all its topics, send an email to v8-users+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages