Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-28282

QDir::canonicalName fails only on Mac OS X due to legacy realpath

    XMLWordPrintable

    Details

    • Platform/s:
      macOS
    • Commits:
      6325c61b475e6560d23348a9dcb26e93c2713647

      Description

      If you compile an executable with -mmacosx-version-min=10.4 that calls QDir::canonicalName with specific paths, incorrect results are returned and the following error is printed to stderr:

      malloc: *** error for object 0xbfffe280: pointer being freed was not allocated

          • set a breakpoint in malloc_error_break to debug

      There are a few conditions:
      1) The path specified must not exist. However, the parent directory of the path must exist. For example, /Applications/foo must not exist, but /Applications must exist.
      2) The Qt library must be compiled with -mmacosx-version-min=10.4. If it is compiled with -mmacosx-version-min=10.5 or greater, the bug will not occur. However, 10.4 is the default.
      3) The running OS must be 10.6 or greater.

      Since the path does not exist, most implementations of realpath should return NULL. However, legacy realpath does not return NULL in this case. It also apparently does not return a pointer to memory allocated with malloc, so attempting to free it causes the error shown above.

      Looking further into this, the problem is that on Mac OSX there are many versions of realpath that could get called.

      • In 10.4, realpath does not support the realpath(X,0) form that requires the caller to free the result. Also, the last component of the path does not need to exist.
      • In 10.5, realpath does not support the realpath(X,0) form, but all components of the path need to exist.
      • In 10.6, realpath supports the realpath(X,0) form, and all components of the path need to exist.

      However, the -mmacosx-version-min flag causes strange behavior. In the documentation this is referred to as legacy mode.

      • Running on 10.4 or 10.5, Qt correctly avoids using realpath since it will not support realpath(X,0).
      • Running on 10.6 or greater, if the flag is set to 10.4, legacy mode is engaged. Legacy realpath does support the realpath(X,0) form that requires the caller to free the result. However, the last component of the path still does not need to exist. This is where this bug occurs.
      • Running on 10.6 or greater, if the flag is set to 10.5 or greater, legacy mode is disabled. realpath does support the realpath(X,0) form that requires the caller to free the result, and the last component of the path must exist.

      The simplest fix would be to always malloc the memory and avoid using the realpath(X,0) form. This avoids the malloc error in all cases. Depending on desired behavior, it may be worthwhile also checking if the path exists before calling realpath to be able to return proper information, but since in theory the file could be deleted by another process at the same time, I don't know if that's important.

        Attachments

        For Gerrit Dashboard: QTBUG-28282
        # Subject Branch Project Status CR V

          Activity

            People

            Assignee:
            jnicholl Jeremy Nicholl
            Reporter:
            jnicholl Jeremy Nicholl
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved:

                Gerrit Reviews

                There are no open Gerrit changes