Skip to content

Commit

Permalink
Lots of additional safety/crash fixes
Browse files Browse the repository at this point in the history
Fixes a bunch of potential startup crashes, and protects against reading incorrect experience data while joining a new game (closes #1)
  • Loading branch information
squeek502 committed Dec 12, 2017
1 parent 0565426 commit 115d964
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 11 deletions.
5 changes: 2 additions & 3 deletions d2info.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ local UPDATE_PERIOD = 1000

while true do
local player = reader:getPlayerName()
if player then
local exp, lvl = reader:getExperience()

local exp, lvl = reader:getExperience()
if player and exp then
if not sessions[player] then
sessions[player] = {}
sessions[player].total = Session.new(exp, lvl)
Expand Down
27 changes: 19 additions & 8 deletions d2info/d2reader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ function D2Reader:init()
local version, err = self.process:version()
if not version then
self.status = "Error obtaining Game.exe version: " .. err
self.process = nil
return
end

Expand Down Expand Up @@ -66,8 +67,10 @@ end
local function openProcessFast()
local window = memreader.findwindow(constants.windowTitle)
if window then
local process = assert(memreader.openprocess(window.pid))
return process.name:lower() == constants.exe:lower() and process or nil
local process = memreader.openprocess(window.pid)
if process and process.name:lower() == constants.exe:lower() then
return process
end
end
end

Expand Down Expand Up @@ -100,7 +103,7 @@ end
function D2Reader:getPlayerPointer()
if not self:checkStatus() then return end
local data, err = self.process:read(self.base + self.offsets.player, 4)
if not data then return nil, err end
if err then return nil, err end
local playerUnitPtr = uint32(data)
return playerUnitPtr ~= 0 and playerUnitPtr or nil
end
Expand All @@ -109,8 +112,10 @@ function D2Reader:getPlayerName()
if not self:checkStatus() then return end
local player = self:getPlayerPointer()
if player then
local unitDataPtr = uint32(self.process:read(player + self.offsets.playerData, 4))
local playerName = self.process:read(unitDataPtr + self.offsets.playerName, 16)
local data, err = self.process:read(player + self.offsets.playerData, 4)
if err then return nil, err end
local unitDataPtr = uint32(data)
local playerName = assert(self.process:read(unitDataPtr + self.offsets.playerName, 16))
return binary.null_terminate(playerName)
end
end
Expand All @@ -119,11 +124,11 @@ function D2Reader:getExperience()
if not self:checkStatus() then return end
local player = self:getPlayerPointer()
if player then
local playerStatListPtr = uint32(self.process:read(player + self.offsets.statList, 4))
local fullStatsData = self.process:read(playerStatListPtr + self.offsets.fullStats, 8)
local playerStatListPtr = uint32(assert(self.process:read(player + self.offsets.statList, 4)))
local fullStatsData = assert(self.process:read(playerStatListPtr + self.offsets.fullStats, 8))
local fullStatsPtr = uint32(fullStatsData)
local fullStatsLength = uint16(fullStatsData, 4)
local fullStatsArray = self.process:read(fullStatsPtr, fullStatsLength * 8)
local fullStatsArray = assert(self.process:read(fullStatsPtr, fullStatsLength * 8))

local exp = 0
local lvl = 1
Expand All @@ -137,6 +142,12 @@ function D2Reader:getExperience()
end
end

-- sanity check: level gets loaded into the array before experience, so check to make sure
-- we're not getting a false 0 experience by comparing exp to level
if exp < constants.experience[lvl] then
return
end

return exp, lvl
end
end
Expand Down

0 comments on commit 115d964

Please sign in to comment.