The TortoiseSVN log files do not rotate or trim, leading to excessive disk usage

35 views
Skip to first unread message

April Zou

unread,
Jun 13, 2024, 6:46:09 AMJun 13
to TortoiseSVN
I noticed that logfile for tortoise can take 4G space of the C disk, which may cause disk shortage. So I reached out to the source code to do secondary development and surprisely found that trimFile function seem not working. 

Screenshot 2024-06-13 170852.png

maxline is set to 4k for default

CLogFile::CLogFile()
{
    m_maxLines = CRegStdDWORD(L"Software\\TortoiseSVN\\MaxLinesInLogfile", 4000);
}

and trimFile function is supposed to handle logFile rotation

void CLogFile::TrimFile(DWORD maxLines) const
{
    if (!PathFileExists(m_logFile.GetWinPath()))
    {
        CTraceToOutputDebugString::Instance()(L"SVNlog::TrimFile: Log file does not exist.");
        return;
    }

    try
    {
        CMappedInFile file(m_logFile.GetWinPath(), true);

        unsigned char* begin = file.GetWritableBuffer();
        unsigned char* end   = begin + file.GetSize();

        CTraceToOutputDebugString::Instance()(L"SVNlog::TrimFile: File path = %s", m_logFile.GetWinPath());
        CTraceToOutputDebugString::Instance()(L"SVNlog::TrimFile: File size = %d bytes", file.GetSize());
        CTraceToOutputDebugString::Instance()(L"SVNlog::TrimFile: begin = 0x%p, end = 0x%p", begin, end);
        CTraceToOutputDebugString::Instance()(L"SVNlog::TrimFile: Number of bytes between begin and end = %d", end - begin);

        if (begin <= (end - 2))
        {
            CTraceToOutputDebugString::Instance()(L"SVNlog::TrimFile: File is too small to trim.");
            return;
        }

        unsigned char* trimPos = begin;
        for (unsigned char* s = end; s != begin; --s)
        {
            if (*(s - 1) == '\n')
            {
                if (maxLines == 0)
                {
                    trimPos = s;
                    break;
                }
                else
                    --maxLines;
            }
        }

        if (trimPos == begin)
        {
            CTraceToOutputDebugString::Instance()(L"SVNlog::TrimFile: No lines need to be trimmed.");
            return;
        }

        CString trimPosStr;
        trimPosStr.Format(L"SVNlog::trimPos: %p", trimPos);
        CTraceToOutputDebugString::Instance()(trimPosStr);

        CString endStr;
        endStr.Format(L"SVNlog::endPos: %p", end);
        CTraceToOutputDebugString::Instance()(endStr);

        size_t newSize = end - trimPos;
        memmove(begin, trimPos, newSize);
        file.Close(newSize);
    }
    catch (CStreamException& e)
    {
        CString errorMsg;
        errorMsg.Format(L"SVNlog::TrimFile: CStreamException while trimming log file: %s", e.what());
        CTraceToOutputDebugString::Instance()(errorMsg);
    }
}

I added some log and use dbgview to capture info, it looks like TrimFile return at byte nums check if (begin <= (end - 2))

I suspect that this condition might be incorrect and should instead be:
if (begin >= (end - 2))

begin >= (end - 2) means the original logFile is less than or equal to 2 bytes which is too small to skip the check. 

Screenshot 2024-06-13 175421.png

Screenshot 2024-06-13 175329.png
```
PS C:\Users\zourui\projects\projfs-tortoisesvn> svn --version
svn, version 1.15.0-unisvn1115 (NTES UNISVN development)
   compiled Jun 11 2024, 18:00:21 on x86-microsoft-windows
```

Daniel Sahlberg

unread,
Jun 13, 2024, 2:41:08 PMJun 13
to TortoiseSVN
Thanks for the report, the analysis is correct. Committed in 29697.

Kind regards,
Daniel
Reply all
Reply to author
Forward
0 new messages