From b4ba3570176bf77aae902b287205513791d7866f Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 11 Nov 2009 21:45:50 +0000 Subject: [PATCH] (svn r18046) [0.7] -Backport from trunk: - Fix: AIs failed to load their data from savegames by crashing them when they tried [FS#3290] (r18038) - Fix: Screen jumped a bit for at least SDL and Allegro when right-click-dragging (r18030) - Fix: [NewGRF] Improve parsing of RIFF data. Skip unknown chunks and check chunk sizes (r17999) - Fix: Count only active clients (not those waiting for map download) when checking min_active_clients limit (r16506) --- src/network/network.cpp | 14 ++++++++--- src/newgrf.cpp | 56 +++++++++++++++++++++++++++++++---------- src/script/squirrel.cpp | 2 +- src/smallmap_gui.cpp | 2 -- src/video/allegro_v.cpp | 4 +-- src/video/allegro_v.h | 2 +- src/video/sdl_v.cpp | 4 +-- src/video/win32_v.cpp | 9 +++---- src/window.cpp | 7 +++++- 9 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/network/network.cpp b/src/network/network.cpp index 4f4ef122e2..5844e50888 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -330,14 +330,20 @@ StringID GetNetworkErrorMsg(NetworkErrorCode err) return network_error_strings[err]; } -/* Count the number of active clients connected */ +/** + * Counts the number of active clients connected. + * It has to be in STATUS_ACTIVE and not a spectator + * @return number of active clients + */ static uint NetworkCountActiveClients() { - const NetworkClientInfo *ci; + const NetworkClientSocket *cs; uint count = 0; - FOR_ALL_CLIENT_INFOS(ci) { - if (IsValidCompanyID(ci->client_playas)) count++; + FOR_ALL_CLIENT_SOCKETS(cs) { + if (cs->status != STATUS_ACTIVE) continue; + if (!IsValidCompanyID(cs->GetInfo()->client_playas)) continue; + count++; } return count; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 1e90f66c00..beefd93ce6 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -41,6 +41,7 @@ #include "map_func.h" #include #include "core/alloc_type.hpp" +#include "core/mem_func.hpp" #include "table/strings.h" #include "table/build_industry.h" @@ -5150,7 +5151,7 @@ static void GRFImportBlock(byte *buf, int len) } } -static void LoadGRFSound(byte *buf, int len) +static void LoadGRFSound(byte *buf, uint len) { byte *buf_start = buf; @@ -5163,22 +5164,31 @@ static void LoadGRFSound(byte *buf, int len) return; } - /* Size of file -- we ignore this */ - grf_load_dword(&buf); + uint32 total_size = grf_load_dword(&buf); + if (total_size > len + 8) { + grfmsg(1, "LoadGRFSound: RIFF was truncated"); + return; + } if (grf_load_dword(&buf) != BSWAP32('WAVE')) { grfmsg(1, "LoadGRFSound: Invalid RIFF type"); return; } - for (;;) { + while (total_size >= 8) { uint32 tag = grf_load_dword(&buf); uint32 size = grf_load_dword(&buf); + total_size -= 8; + if (total_size < size) { + grfmsg(1, "LoadGRFSound: Invalid RIFF"); + return; + } + total_size -= size; switch (tag) { case ' tmf': // 'fmt ' /* Audio format, must be 1 (PCM) */ - if (grf_load_word(&buf) != 1) { + if (size < 16 || grf_load_word(&buf) != 1) { grfmsg(1, "LoadGRFSound: Invalid audio format"); return; } @@ -5188,13 +5198,13 @@ static void LoadGRFSound(byte *buf, int len) grf_load_word(&buf); se->bits_per_sample = grf_load_word(&buf); - /* Consume any extra bytes */ - for (; size > 16; size--) grf_load_byte(&buf); + /* The rest will be skipped */ + size -= 16; break; case 'atad': // 'data' se->file_size = size; - se->file_offset = FioGetPos() - (len - (buf - buf_start)) + 1; + se->file_offset = FioGetPos() - (len - (buf - buf_start)); se->file_slot = _file_index; /* Set default volume and priority */ @@ -5202,13 +5212,21 @@ static void LoadGRFSound(byte *buf, int len) se->priority = 0; grfmsg(2, "LoadGRFSound: channels %u, sample rate %u, bits per sample %u, length %u", se->channels, se->rate, se->bits_per_sample, size); - return; + return; // the fmt chunk has to appear before data, so we are finished default: - se->file_size = 0; - return; + /* Skip unknown chunks */ + break; } + + /* Skip rest of chunk */ + for (; size > 0; size--) grf_load_byte(&buf); } + + grfmsg(1, "LoadGRFSound: RIFF does not contain any sound data"); + + /* Clear everything that was read */ + MemSetT(se, 0); } /* Action 0x12 */ @@ -5347,22 +5365,34 @@ static void TranslateGRFStrings(byte *buf, size_t len) /* 'Action 0xFF' */ static void GRFDataBlock(byte *buf, int len) { + /* '\0' */ + if (_grf_data_blocks == 0) { grfmsg(2, "GRFDataBlock: unexpected data block, skipping"); return; } + if (!check_length(len, 3, "GRFDataBlock")) return; + buf++; uint8 name_len = grf_load_byte(&buf); const char *name = (const char *)buf; - buf += name_len + 1; + buf += name_len; + + /* Test string termination */ + if (grf_load_byte(&buf) != 0) { + grfmsg(2, "GRFDataBlock: Name not properly terminated"); + return; + } + + if (!check_length(len, 3 + name_len, "GRFDataBlock")) return; grfmsg(2, "GRFDataBlock: block name '%s'...", name); _grf_data_blocks--; switch (_grf_data_type) { - case GDT_SOUND: LoadGRFSound(buf, len - name_len - 2); break; + case GDT_SOUND: LoadGRFSound(buf, len - name_len - 3); break; default: NOT_REACHED(); break; } } diff --git a/src/script/squirrel.cpp b/src/script/squirrel.cpp index c165a1b987..b27de90cb3 100644 --- a/src/script/squirrel.cpp +++ b/src/script/squirrel.cpp @@ -222,7 +222,7 @@ bool Squirrel::CallMethod(HSQOBJECT instance, const char *method_name, HSQOBJECT if (ret != NULL) sq_getstackobj(vm, -1, ret); /* Reset the top, but don't do so for the AI main function, as we need * a correct stack when resuming. */ - if (suspend == -1) sq_settop(this->vm, top); + if (suspend == -1 || !this->IsSuspended()) sq_settop(this->vm, top); /* Restore the return-value location. */ this->vm->_suspended_target = last_target; diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 1d5c2baca0..9cfc64d953 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -981,8 +981,6 @@ public: if (widget == SM_WIDGET_MAP) { if (_scrolling_viewport) return; _scrolling_viewport = true; - _cursor.delta.x = 0; - _cursor.delta.y = 0; } } diff --git a/src/video/allegro_v.cpp b/src/video/allegro_v.cpp index b376d1aec4..ac7d4455be 100644 --- a/src/video/allegro_v.cpp +++ b/src/video/allegro_v.cpp @@ -368,8 +368,8 @@ static void PollEvent() int dy = mouse_y - _cursor.pos.y; if (dx != 0 || dy != 0) { if (_cursor.fix_at) { - _cursor.delta.x += dx; - _cursor.delta.y += dy; + _cursor.delta.x = dx; + _cursor.delta.y = dy; position_mouse(_cursor.pos.x, _cursor.pos.y); } else { _cursor.delta.x = dx; diff --git a/src/video/allegro_v.h b/src/video/allegro_v.h index 6f420c7328..347acc364c 100644 --- a/src/video/allegro_v.h +++ b/src/video/allegro_v.h @@ -24,7 +24,7 @@ public: class FVideoDriver_Allegro: public VideoDriverFactory { public: - static const int priority = 5; + static const int priority = 4; /* virtual */ const char *GetName() { return "allegro"; } /* virtual */ const char *GetDescription() { return "Allegro Video Driver"; } /* virtual */ Driver *CreateInstance() { return new VideoDriver_Allegro(); } diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index cd7b55e8cf..4e0a177242 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -334,8 +334,8 @@ static int PollEvent() int dx = ev.motion.x - _cursor.pos.x; int dy = ev.motion.y - _cursor.pos.y; if (dx != 0 || dy != 0) { - _cursor.delta.x += dx; - _cursor.delta.y += dy; + _cursor.delta.x = dx; + _cursor.delta.y = dy; SDL_CALL SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y); } } else { diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index f4d61c431c..e8b3c60fbe 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -426,8 +426,8 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP int dx = x - _cursor.pos.x; int dy = y - _cursor.pos.y; if (dx != 0 || dy != 0) { - _cursor.delta.x += dx; - _cursor.delta.y += dy; + _cursor.delta.x = dx; + _cursor.delta.y = dy; pt.x = _cursor.pos.x; pt.y = _cursor.pos.y; @@ -436,8 +436,8 @@ static LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP SetCursorPos(pt.x, pt.y); } } else { - _cursor.delta.x += x - _cursor.pos.x; - _cursor.delta.y += y - _cursor.pos.y; + _cursor.delta.x = x - _cursor.pos.x; + _cursor.delta.y = y - _cursor.pos.y; _cursor.pos.x = x; _cursor.pos.y = y; _cursor.dirty = true; @@ -872,7 +872,6 @@ void VideoDriver_Win32::MainLoop() if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); GameLoop(); - _cursor.delta.x = _cursor.delta.y = 0; if (_force_full_redraw) MarkWholeScreenDirty(); diff --git a/src/window.cpp b/src/window.cpp index b9b42cd617..10ee2591b4 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1900,7 +1900,7 @@ static void HandleKeyScrolling() } } -void MouseLoop(MouseClick click, int mousewheel) +static void MouseLoop(MouseClick click, int mousewheel) { DecreaseWindowCounters(); HandlePlacePresize(); @@ -2043,6 +2043,11 @@ void HandleMouseEvents() } MouseLoop(click, mousewheel); + + /* We have moved the mouse the required distance, + * no need to move it at any later time. */ + _cursor.delta.x = 0; + _cursor.delta.y = 0; } /**