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

[Matrix] fix crash and freeze problem from wrong file seek #82

Merged
merged 5 commits into from
Apr 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/UnrarXLib/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,10 @@ bool File::RawSeek(int64 Offset,int Method)
if (Offset > FileLength())
return false;

// Worst safe case, to prevent seek lower as 0
if (Offset < 0 && Offset + hFile->GetPosition() < 0)
Offset = 0;

if (hFile->Seek(Offset,Method) < 0)
return false;
#else
Expand Down
4 changes: 3 additions & 1 deletion lib/UnrarXLib/file.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,9 @@ class File
#endif
static size_t CopyBufferSize()
{
#ifdef _WIN_ALL
#if defined(BUILD_KODI_ADDON)
return 0x40000;
#elif defined(_WIN_ALL)
// USB flash performance is poor with 64 KB buffer, 256+ KB resolved it.
// For copying from HDD to same HDD the best performance was with 256 KB
// buffer in XP and with 1 MB buffer in Win10.
Expand Down
34 changes: 19 additions & 15 deletions lib/UnrarXLib/rdwrfn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
if (!SrcFile->IsOpened())
{
NextVolumeMissing = true;
return(-1);
return -1;
}
if (UnpackToMemory)
{
Expand All @@ -89,48 +89,52 @@ int ComprDataIO::UnpRead(byte *Addr,size_t Count)
if (m_iSeekTo > CurUnpStart+SrcArc->FileHead.PackSize) // need to seek outside this block
{
TotalRead += (int)(SrcArc->NextBlockPos-SrcFile->Tell());
CurUnpRead=CurUnpStart+SrcArc->FileHead.PackSize;
UnpPackedSize=0;
CurUnpRead = CurUnpStart+SrcArc->FileHead.PackSize;
UnpPackedSize = 0;
ReadSize = 0;
bRead = false;
}
else
{
int64 iSeekTo;
size_t MaxWinSize = File::CopyBufferSize();
int64 iStartOfFile = SrcArc->NextBlockPos-SrcArc->FileHead.PackSize;
m_iStartOfBuffer = CurUnpStart;
int64 iSeekTo=m_iSeekTo-CurUnpStart<MaxWinSize/2?iStartOfFile:iStartOfFile+m_iSeekTo-CurUnpStart-MaxWinSize/2;
if (iSeekTo == iStartOfFile) // front

if (m_iSeekTo - CurUnpStart < MaxWinSize / 2) // front
{
if (CurUnpStart+MaxWinSize>SrcArc->FileHead.UnpSize)
iSeekTo = iStartOfFile;

if (CurUnpStart + MaxWinSize > SrcArc->FileHead.UnpSize)
{
m_iSeekTo=iStartOfFile;
m_iSeekTo = iStartOfFile;
UnpPackedSize = SrcArc->FileHead.PackSize;
}
else
{
m_iSeekTo=MaxWinSize-(m_iSeekTo-CurUnpStart);
m_iSeekTo = MaxWinSize - (m_iSeekTo - CurUnpStart);
UnpPackedSize = SrcArc->FileHead.PackSize - (m_iStartOfBuffer - CurUnpStart);
}
}
else
{
m_iStartOfBuffer = m_iSeekTo-MaxWinSize/2; // front
if (m_iSeekTo+MaxWinSize/2>SrcArc->FileHead.UnpSize)
m_iStartOfBuffer = m_iSeekTo - MaxWinSize / 2; // front
m_iSeekTo = MaxWinSize - (m_iSeekTo - m_iStartOfBuffer);
if (m_iSeekTo + MaxWinSize / 2 > SrcArc->FileHead.UnpSize)
{
iSeekTo = iStartOfFile+SrcArc->FileHead.PackSize-MaxWinSize;
m_iStartOfBuffer = CurUnpStart+SrcArc->FileHead.PackSize-MaxWinSize;
m_iSeekTo = MaxWinSize-(m_iSeekTo-m_iStartOfBuffer);
iSeekTo = iStartOfFile + SrcArc->FileHead.PackSize - MaxWinSize;
m_iStartOfBuffer = CurUnpStart + SrcArc->FileHead.PackSize - MaxWinSize;
UnpPackedSize = MaxWinSize;
}
else
{
m_iSeekTo=MaxWinSize/2;
iSeekTo = iStartOfFile + m_iStartOfBuffer - CurUnpStart;
m_iSeekTo = MaxWinSize / 2;
UnpPackedSize = SrcArc->FileHead.PackSize - (m_iStartOfBuffer - CurUnpStart);
}
}

SrcFile->Seek(iSeekTo,SEEK_SET);
SrcFile->Seek(iSeekTo, SEEK_SET);

TotalRead = 0;
CurUnpRead = CurUnpStart + iSeekTo - iStartOfFile;
Expand Down
2 changes: 1 addition & 1 deletion src/RarExtractThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void CRarFileExtractThread::Process()
}
catch (...)
{
kodiLog(ADDON_LOG_ERROR, "CFileRarExtractThread::%s: failed. CmdExtract::ExtractCurrentFile threw an Unknown exception", __func__);
kodiLog(ADDON_LOG_ERROR, "CFileRarExtractThread::%s: failed. CmdExtract::ExtractCurrentFile threw an Unknown exception (error code of %d)", __func__, ErrHandler.GetErrorCode());
}

hRunning.Reset();
Expand Down
11 changes: 11 additions & 0 deletions src/RarFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ ssize_t CRARFile::Read(void* context, void* lpBuf, size_t uiBufSize)
uicBufSize -= copy;
}

int tries = 3; // Retry amount, TODO: maybe increase if on smaller devices still problems occur?
while ((uicBufSize > 0) && ctx->m_fileposition < ctx->m_size)
{
if (ctx->m_inbuffer <= 0)
Expand All @@ -157,10 +158,20 @@ ssize_t CRARFile::Read(void* context, void* lpBuf, size_t uiBufSize)
// invalid data returned by UnrarXLib, prevent a crash
kodiLog(ADDON_LOG_ERROR, "CRarFile::%s: Data buffer in inconsistent state", __func__);
ctx->m_inbuffer = 0;
break;
}

if (ctx->m_inbuffer == 0)
{
// If buffer size was 0, retry few times to prevent delay problems on
// unrar process thread. Without it can have inside Kodi problems as
// his requested size not returned. Specially Kodi's BluRay support
// have a bug about and stops playback if returned size differ to
// often from requested size.
if (tries-- > 0)
continue;
break;
}

ssize_t copy = std::min(static_cast<ssize_t>(ctx->m_inbuffer), uicBufSize);
if (copy + ctx->m_fileposition >= ctx->m_size)
Expand Down
8 changes: 7 additions & 1 deletion vfs.rar/addon.xml.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<addon
id="vfs.rar"
version="3.3.0"
version="3.3.1"
name="RAR archive support"
provider-name="spiff">
<requires>@ADDON_DEPENDS@</requires>
Expand All @@ -15,7 +15,13 @@
encodedhostname="true"
library_@PLATFORM@="@LIBRARY_FILENAME@" />
<extension point="xbmc.addon.metadata">
<summary lang="de_DE">Entpacker für .rar Dateien</summary>
<summary lang="en_GB">Unarchiver for .rar files</summary>
<description lang="de_DE">Dieses Addon dient zum entpacken von RAR-Archiven.

Es ermöglicht das direkte Lesen nicht komprimierter RAR-Dateien, sodass ein vorheriges Entpacken nicht erforderlich ist. Bei allen anderen Typen wird es vorübergehend entpackt und an Kodi übertragen.

Achtung: Der Archivtyp "Solid RAR" erfordert ein vollständiges Entpacken, um die darin enthaltenen Dateien zu verwenden. Daher können die Zugriffszeiten für größere Pakete länger dauern.</description>
<description lang="en_GB">This addon is an extraction utility for RAR archives.

It allows direct reading of uncompressed RAR files, so prior unpacking is not necessary. For all other types, it is temporarily unpacked and passed to Kodi.
Expand Down
83 changes: 83 additions & 0 deletions vfs.rar/resources/language/resource.language.de_de/strings.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Kodi Media Center language file
# Addon Name: Archive support
# Addon id: vfs.rar
# Addon Provider: Team Kodi
msgid ""
msgstr ""
"Project-Id-Version: KODI Main\n"
"Report-Msgid-Bugs-To: https://github.com/xbmc/vfs.rar/issues/\n"
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Kodi Translation Team\n"
"Language-Team: German (Germany) (http://www.transifex.com/projects/p/kodi-main/language/de_DE/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: de_DE\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#[Consistency] Make terms, settings names, brands and other minutiae, consistent throughout file.
#[Capitalization] Avoid capitalizing every second word. See http://grammarist.com/capitalization/
#For example, prefer wording as "This new string" instead of "This New String".
#[Referencing] If a suitable string already exists, reuse it, making a note of where it's used!
#[Description / location] For example, "#. Description of some setting" used on "#: xbmc/addons/guidialogaddoninfo.cpp"
#When writing a description or setting, refer to a setting name in quotes. See existing entries for guidance.
#For example, "Press \"OK\" for \"All seasons\"" instead of "Press OK for All seasons" after first word.

msgctxt "#30000"
msgid "RAR file extract"
msgstr "RAR-Datenextrakt"

msgctxt "#30001"
msgid "RAR file scan"
msgstr "RAR-Dateiprüfung"

msgctxt "#30002"
msgid "RAR solid file scan"
msgstr "Solid RAR-Dateiprüfung"

msgctxt "#30003"
msgid "Enter RAR package password for:\n%s"
msgstr "Geben Sie das RAR-Paketkennwort ein für:\n%s"

msgctxt "#30004"
msgid "Not enough disk space available"
msgstr "Nicht genügend Speicherplatz verfügbar"

# Following strings used for addon settings dialog

msgctxt "#30010"
msgid "General"
msgstr "Allgemein"

msgctxt "#30011"
msgid "Ask for password"
msgstr "Frage nach dem Passwort"

msgctxt "#30012"
msgid "If archives are password protected, prompt for the password to be entered"
msgstr "Wenn Archive durch ein Passwort geschützt sind, werden Sie aufgefordert, das Passwort einzugeben"

msgctxt "#30013"
msgid "Pre-defined password to attempt decompression with"
msgstr "Vordefiniertes Passwort für den Versuch der Dekomprimierung"

msgctxt "#30014"
msgid "Stored password 1"
msgstr "Gespeichertes Passwort 1"

msgctxt "#30015"
msgid "Stored password 2"
msgstr "Gespeichertes Passwort 2"

msgctxt "#30016"
msgid "Stored password 3"
msgstr "Gespeichertes Passwort 3"

msgctxt "#30017"
msgid "Stored password 4"
msgstr "Gespeichertes Passwort 4"

msgctxt "#30018"
msgid "Stored password 5"
msgstr "Gespeichertes Passwort 5"