ComputerCraft

ComputerCraft

21M Downloads

GPS.locate can crash CC computer

Lupus590 opened this issue ยท 3 comments

commented

Original post on forum: http://www.computercraft.info/forums2/index.php?/topic/27427-crash-any-computer-using-gpslocate/#entry258294

OP (Edited): Code which caused crash
Gps.locate only verifies that the gps host is sending a table with 3 coords, but doesn't test to see if the coords are numbers. Sending three tables is enough to trip up the attempt to tostring the vector.

While investigating this I also noticed that the vector.new doesn't verify that it has received numbers.
I've made an untested bug fix though:

-- vector API
-- Make sure args are numbers
function new( x, y, z )
local v = {
  x = tonumber(x) or 0,
  y = tonumber(y) or 0,
  z = tonumber(z) or 0
}
setmetatable( v, vmetatable )
return v
end
-- GPS API
-- Make sure GPS host positions are not nil
function locate( _nTimeout, _bDebug )
    -- Let command computers use their magic fourth-wall-breaking special abilities
    if commands then
        return commands.getBlockPosition()
    end
-- Find a modem
local sModemSide = nil
for n,sSide in ipairs( rs.getSides() ) do
  if peripheral.getType( sSide ) == "modem" and peripheral.call( sSide, "isWireless" ) then
   sModemSide = sSide
   break
  end
end
if sModemSide == nil then
  if _bDebug then
   print( "No wireless modem attached" )
  end
  return nil
end

if _bDebug then
  print( "Finding position..." )
end

-- Open a channel
local modem = peripheral.wrap( sModemSide )
local bCloseChannel = false
if not modem.isOpen( os.getComputerID() ) then
  modem.open( os.getComputerID() )
  bCloseChannel = true
end

-- Send a ping to listening GPS hosts
modem.transmit( CHANNEL_GPS, os.getComputerID(), "PING" )

-- Wait for the responses
local tFixes = {}
local pos1, pos2 = nil, nil
sBadPositionError = "GPS replied with bad position, check your GPS hosts."
local timeout = os.startTimer( _nTimeout or 2 )
while true do
  local e, p1, p2, p3, p4, p5 = os.pullEvent()
  if e == "modem_message" then
   -- We received a reply from a modem
   local sSide, sChannel, sReplyChannel, tMessage, nDistance = p1, p2, p3, p4, p5
   if sSide == sModemSide and sChannel == os.getComputerID() and sReplyChannel == CHANNEL_GPS and nDistance then
    -- Received the correct message from the correct modem: use it to determine position
    if type(tMessage) == "table" and #tMessage == 3 then
     local tFix = { vPosition = vector.new( assert(tMessage[1], sBadPositionError), assert(tMessage[2], sBadPositionError),assert(tMessage[3], sBadPositionError) ), nDistance = nDistance }
     if _bDebug then
      print( tFix.nDistance.." metres from "..tostring( tFix.vPosition ) )
     end
     if tFix.nDistance == 0 then
         pos1, pos2 = tFix.vPosition, nil
     else
                        table.insert( tFixes, tFix )
                        if #tFixes >= 3 then
                            if not pos1 then
                                pos1, pos2 = trilaterate( tFixes[1], tFixes[2], tFixes[#tFixes] )
                            else
                                pos1, pos2 = narrow( pos1, pos2, tFixes[#tFixes] )
                            end
                        end
                    end
     if pos1 and not pos2 then
      break
     end
    end
   end

  elseif e == "timer" then
   -- We received a timeout
   local timer = p1
   if timer == timeout then
    break
   end

  end
end

-- Close the channel, if we opened one
if bCloseChannel then
  modem.close( os.getComputerID() )
end

-- Return the response
if pos1 and pos2 then
  if _bDebug then
   print( "Ambiguous position" )
   print( "Could be "..pos1.x..","..pos1.y..","..pos1.z.." or "..pos2.x..","..pos2.y..","..pos2.z )
  end
  return nil
elseif pos1 then
  if _bDebug then
   print( "Position is "..pos1.x..","..pos1.y..","..pos1.z )
  end
  return pos1.x, pos1.y, pos1.z
else
  if _bDebug then
   print( "Could not determine position" )
  end
  return nil
end
end
commented

Downsides of not using a language with static typing I suppose ๐Ÿ˜›

commented

I made a temporary resource pack to patch both bugs.

commented

I put it on the form post