Log caching: Crash in `Get merge logs' without access to the repository root

Evgeny Kotkov <[email protected]>
Newsgroups gmane.comp.version-control.subversion.tortoisesvn.devel
Message-ID <CAP_GPNgP-8Md6WZRmRJqrdtS4fiG4N8365Neis_78Eevg9z1aA@mail.gmail.com>
The `Get merge logs' command can cause a segfault in TortoiseSVN 1.9.3.

The crash is also reproducible in trunk@r27234 and is caused by an access
violation (out of bounds access in an std::vector) in the implementation of
the log caching.  Please note that it should be reproducible irrespectively
of whether the log caching feature is enabled or disabled in the settings.

Reproduction script:

 1. Create a repository with a /trunk folder hosted by httpd
 2. Prohibit access to the root of the repository
 3. Allow rw access to /trunk
 4. In the TortoiseSVN log viewer, click `Get merge logs' for /trunk or,
    alternatively, run the following command:
    TortoiseProc /command:log /path:"http://localhost/repository/trunk" /merge

Backtrace of the TortoiseProc.exe crash, uploaded with DumpID=7261138:

    TortoiseProc.exe!LogCache::CRevisionInfoContainer::GetAuthorID(
        index=4294967295)
    TortoiseProc.exe!CCacheLogQuery::SendToReceiver(
        revision=1, options={...}, mergeInfo=0x000000b1942fd834)
    TortoiseProc.exe!CCacheLogQuery::LogRevision(
        revision=1, options={...}, mergeInfo=0x000000b1942fd834)
    TortoiseProc.exe!CCacheLogQuery::CMergeLogger::ReceiveLog(
        changes=0x0, rev=1, stdRevProps=0x0, userRevProps=0x0,
        mergeInfo=0x000000b1942fd834)
    TortoiseProc.exe!CSVNLogQuery::LogReceiver()
    libsvn_tsvn.dll!log_closed()
    libsvn_tsvn.dll!xml_cb_end()
    libsvn_tsvn.dll!expat_end()
    libaprutil_tsvn.dll!doContent()
    libaprutil_tsvn.dll!contentProcessor()
    libaprutil_tsvn.dll!doProlog()
    libaprutil_tsvn.dll!prologProcessor()
    libaprutil_tsvn.dll!prologInitProcessor()
    libaprutil_tsvn.dll!XML_ParseBuffer()
    libaprutil_tsvn.dll!XML_Parse()
    libsvn_tsvn.dll!expat_response_handler()
    libsvn_tsvn.dll!handle_response()
    libsvn_tsvn.dll!handle_response_cb()
    libsvn_tsvn.dll!read_from_connection()
    libsvn_tsvn.dll!serf__process_connection()
    libsvn_tsvn.dll!serf_event_trigger()
    libsvn_tsvn.dll!serf_context_run()
    libsvn_tsvn.dll!svn_ra_serf__context_run()
    libsvn_tsvn.dll!svn_ra_serf__get_log()
    libsvn_tsvn.dll!svn_ra_get_log2()
    libsvn_tsvn.dll!run_ra_get_log()
    libsvn_tsvn.dll!svn_client_log5()
    TortoiseProc.exe!CSVNLogQuery::Log()
    TortoiseProc.exe!CCacheLogQuery::InternalLogWithMerge()
    TortoiseProc.exe!CCacheLogQuery::Log()
    TortoiseProc.exe!SVN::ReceiveLog()
    ...

Here is what happens over the network in this case:

  OPTIONS http://localhost/repository/trunk HTTP/1.1  (200 OK)
  OPTIONS http://localhost/repository/trunk HTTP/1.1  (200 OK)
  OPTIONS http://localhost/repository/trunk HTTP/1.1  (200 OK)
  OPTIONS http://localhost/repository/trunk HTTP/1.1  (200 OK)
  OPTIONS http://localhost/repository/trunk HTTP/1.1  (200 OK)
  OPTIONS http://localhost/repository/trunk HTTP/1.1  (200 OK)
  OPTIONS http://localhost/repository/trunk HTTP/1.1  (200 OK)
  REPORT http://localhost/repository/!svn/rvr/1/trunk HTTP/1.1  (200 OK)
      Request:
        <S:log-report xmlns:S="svn:">
          <S:start-revision>1</S:start-revision>
          <S:end-revision>0</S:end-revision>
          <S:limit>100</S:limit>
          <S:include-merged-revisions/>
          <S:all-revprops/>
          <S:path></S:path>
          <S:encode-binary-props/>
        </S:log-report>
      Response:
        <S:log-report xmlns:S="svn:" xmlns:D="DAV:">
          <S:log-item>
          <D:version-name>1</D:version-name>
          <D:creator-displayname>Author</D:creator-displayname>
          <S:date>2016-03-09T10:08:06.624980Z</S:date>
          </S:log-item>
        </S:log-report>
  OPTIONS http://localhost/repository HTTP/1.1  (403 Forbidden)

Another thing worth mentioning is the overall performance of the operation.
If I allow access to the repository root, the `Get merge logs' command does
a huge amount of REPORT requests to the server, and that can be very slow,
especially considering that every REPORT creates a new TCP connection.

Here is what happens over the network when I display a part of the log for
/branches/1.3.x in the repository containing 1455 revisions (even with the
log caching feature disabled):

  REPORT http://localhost/repository/!svn/rvr/1455/branches/1.3.x
      start: 1455, end: 0, limit: 100, { all revprops }, include merged
  REPORT http://localhost/repository/!svn/rvr/1446
      start: 1446, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1333
      start: 1333, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1341
      start: 1341, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1228
      start: 1228, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1231
      start: 1231, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1087
      start: 1087, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1091
      start: 1091, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1233
      start: 1233, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1124
      start: 1124, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/1128
      start: 1128, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  REPORT http://localhost/repository/!svn/rvr/886
      start: 886, end: 0, limit: 100, { svn:log, svn:date, svn:author }
  ...

  (Compared to that, the svn log -g does only a single REPORT).

In a network with RTT=150ms, showing the same log with TortoiseSVN could
be up to 15-20 times slower than with the command-line client — something
like 2 seconds (svn.exe) vs 35 seconds (TortoiseProc.exe) in this particular
case.


Regards,
Evgeny Kotkov

------------------------------------------------------
http://tortoisesvn.tigris.org/ds/viewMessage.do?dsForumId=757&dsMessageId=3165025

To unsubscribe from this discussion, e-mail: [[email protected]].
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.