Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

call on nil segfaults #78

Closed
kokizzu opened this issue Mar 17, 2015 · 7 comments
Closed

call on nil segfaults #78

kokizzu opened this issue Mar 17, 2015 · 7 comments
Assignees

Comments

@kokizzu
Copy link

kokizzu commented Mar 17, 2015

I'm trying to make a program that print 100k-th odd prime number until 10M. The stackoverflow question.

last = 3 
res = (last) # create array
loop:
   last += 2
   prime = true 
   len = res length -1
   i = 0
   while(i<len):
      v = res at(i)
      if(v*v > last): break.
      if(last%v == 0): prime = false, break.
      i += 1
   .
   if(prime):
          res append(last)
          if(res size % 100000 == 0): last print.
          if(last>9999999): break.
   .
.

But it gives Segmentation fault (core dumped)
For reference, the working ruby version:

res = [last=3]
loop do 
   last += 2
   prime = true
   res.each do |v|
          break if v*v > last 
          if last % v == 0 
        prime = false 
        break
      end
   end
   if prime
     res << last 
     puts last if res.length % 100000 == 0 
     break if last > 9999999
   end
end
@rurban
Copy link
Member

rurban commented Mar 17, 2015

As you found out on stackoverflow, size needs to be length, as in ruby. A call on nil segfaults unfortunately.
A method on nil just silently fails as you also found out in #79.

https://stackoverflow.com/questions/29091475/printing-odd-prime-every-100k-primes-found/29096987#29096987

@rurban rurban self-assigned this Mar 17, 2015
@rurban rurban changed the title [Ask] segmentation fault call on nil segfaults Mar 17, 2015
@robotii
Copy link
Contributor

robotii commented Aug 4, 2015

Related to this most probably, the comparison operators also segfault on nil. You can see this by running example/palindrome.pn with no arguments. With the -B switch it completes successfully, but segfaults under the jit.

@rurban
Copy link
Member

rurban commented Oct 13, 2015

The question is if we should slow down jit by checking argument types or not.
So far I check with a debugging potion, and not without.

@robotii
Copy link
Contributor

robotii commented Oct 16, 2015

I don't think it's necessary to type check arguments.

The problem is in potion_x86_call, where it doesn't check for nil before attempting to dereference memory. I think this needs to be added to the beginning of the function, otherwise it attempts to call potion_obj_get_call which returns nil, which is then attempted to be deferenced as a memory location.

Alternatively, the necessary code could be added just after the lines (in vm-x86.c)

      //[b]: got the method, call it (first special slot from PNClosure)
      TAG_LABEL(tag_b);

The memory deference for nil is in the line immediately following this.

I'm not sure where the best place is to put it, nor do I have the necessary ASM skills to do the modification myself.

@rurban
Copy link
Member

rurban commented Oct 16, 2015

On Oct 16, 2015, at 5:44 PM, Peter Arthur notifications@github.com wrote:

I don't think it's necessary to type check arguments.

The problem is in potion_x86_call, where it doesn't check for nil before attempting to dereference memory. I think this needs to be added to the beginning of the function, otherwise it attempts to call potion_obj_get_call which returns nil, which is then attempted to be deferenced as a memory location.

Alternatively, the necessary code could be added just after the lines (in vm-x86.c)

  //[b]: got the method, call it (first special slot from PNClosure)

TAG_LABEL(tag_b);
The memory deference for nil is in the line immediately following this.

Good idea. That would be only 2 lines.

I'm not sure where the best place is to put it, nor do I have the necessary ASM skills to do the modification myself.

I’ll try when I have a bit more time.

@robotii
Copy link
Contributor

robotii commented Oct 16, 2015

Hi @rurban

I've dug a bit deeper into this. This particular issue is caused by potion_object_size, which attempts to return the size of the object.

Unfortunately, there are a few problems with this function.

  1. The number returned is a raw number, and needs to be wrapped in PN_NUM() macro in order for it to return the correct value to the caller.
  2. The function is not GC aware, which means that if it gets passed a FWD struct, it will fail horribly.
  3. The function does not consider non-pointer objects, such as PN_TRUE, PN_FALSE and PN_NUM.

I can confirm that the original code does not segfault when the line

potion_method(obj_vt, "size", potion_object_size, 0);

is commented out, indicating this is the problem.

Changing the vm call function would not fix this problem, although it wouldn't hurt to still make those changes. In fact, I think the current code correctly handles null

I really don't think this function is that useful and personally I would remove it unless we can find a reason to keep it. It can quite easily be confused with the length method, as we have already seen.

rurban pushed a commit that referenced this issue Oct 17, 2015
This is used as size method but did not return a PN_NUM
just a raw integer. It also failed on non-objects.
Return 0 for wrong objects, the number of bytes for primitives and objects.
Fixes GH #78, thanks to @robotii for the correct analysis
@rurban
Copy link
Member

rurban commented Oct 17, 2015

Just fixed it, thanks.
length vs size methods:

  • length is defined for tuples, tables, str and bytes, returning the number of elements
  • size is defined of all objects and now also for all primitives, returning the number of used bytes for the members and fields, but not for variable length data, like str, bytes.

size is a bit ill-defined and currently not used, yes. But I'll keep it asis for now

@rurban rurban closed this as completed Oct 17, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants