    protected function getFullPath($path, $base)
    {
        $separator = $this->separator;
        $systemroot = $this->systemRoot;
        $base = (string)$base;

        if ($base[0] === $separator && substr($base, 0, strlen($systemroot)) !== $systemroot) {
            $base = $systemroot . substr($base, 1);
        }
        if ($base !== $systemroot) {
            $base = rtrim($base, $separator);
        }

        // 'Here'
        if ($path === '' || $path === '.' . $separator) return $base;

        $sepquoted = preg_quote($separator, '#');

        if (substr($path, 0, 3) === '..' . $separator) {
            $path = $base . $separator . $path;
        }
        // normalize `/../`
        $normreg = '#(' . $sepquoted . ')[^' . $sepquoted . ']+' . $sepquoted . '\.\.' . $sepquoted . '#'; // '#(/)[^\/]+/\.\./#'
        while (preg_match($normreg, $path)) {
            $path = preg_replace($normreg, '$1', $path, 1);
        }
        if ($path !== $systemroot) {
            $path = rtrim($path, $separator);
        }

        // Absolute path
        if ($path[0] === $separator || strpos($path, $systemroot) === 0) {
            return $path;
        }

        $preg_separator = '#' . $sepquoted . '#';

        // Relative path from 'Here'
        if (substr($path, 0, 2) === '.' . $separator || $path[0] !== '.') {
            $arrn = preg_split($preg_separator, $path, -1, PREG_SPLIT_NO_EMPTY);
            if ($arrn[0] !== '.') {
                array_unshift($arrn, '.');
            }
            $arrn[0] = rtrim($base, $separator);
            return join($separator, $arrn);
        }

        return $path;
    }
The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.