From 52804d587430ece02e9d2e4e0bf5a947f82bf6b6 Mon Sep 17 00:00:00 2001 From: Herman Venter Date: Fri, 21 Jun 2013 11:11:23 -0700 Subject: [PATCH] Generalize breakpoint matching involving relative paths Currently a breakpoint specified as relativefilepath:lineno will match only if the relative file path is a simple file name or if sandbox root + relative file path is an exact match. This is now generalized so that matching occurs if the relative file path is a suffix (path) of the absolute path of the execution location. --- hphp/runtime/debugger/break_point.cpp | 25 +++++++++++++-------- hphp/runtime/debugger/break_point.h | 3 +-- hphp/runtime/vm/debugger_hook.cpp | 8 +++---- hphp/test/quick/debugger/break2.php.expectf | 12 +++++----- hphp/test/quick/debugger/break2.php.in | 2 +- 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/hphp/runtime/debugger/break_point.cpp b/hphp/runtime/debugger/break_point.cpp index 4bf4989f7..6a901b5a4 100644 --- a/hphp/runtime/debugger/break_point.cpp +++ b/hphp/runtime/debugger/break_point.cpp @@ -829,21 +829,28 @@ bool BreakPointInfo::MatchFile(const char *haystack, int haystack_len, return false; } +// Returns true if file is a suffix path of fullPath bool BreakPointInfo::MatchFile(const std::string& file, - const std::string& fullPath, - const std::string& relPath) { + const std::string& fullPath) { TRACE(2, "BreakPointInfo::MatchFile(const std::string&\n"); - if (file == fullPath || file == relPath) { + if (file == fullPath) { return true; } - if (file.find('/') == std::string::npos && - file == fullPath.substr(fullPath.rfind('/') + 1)) { + if (file.size() > 0 && file[0] != '/') { + auto pos = fullPath.rfind(file); + // check for match + if (pos == std::string::npos) return false; + // check if match is a suffix + if (pos + file.size() > fullPath.size()) return false; + // check if suffix is a sub path + if (pos == 0 || fullPath[pos-1] != '/') return false; return true; } - // file is possibly setup with a symlink in the path - if (StatCache::realpath(file.c_str()) == - StatCache::realpath(fullPath.c_str())) { - return true; + // Perhaps file or fullPath is a symlink. + auto realFile = StatCache::realpath(file.c_str()); + auto realFullPath = StatCache::realpath(fullPath.c_str()); + if (realFile != file || realFullPath != fullPath) { + return MatchFile(realFile, realFullPath); } return false; } diff --git a/hphp/runtime/debugger/break_point.h b/hphp/runtime/debugger/break_point.h index 3c702c008..c7df820bc 100644 --- a/hphp/runtime/debugger/break_point.h +++ b/hphp/runtime/debugger/break_point.h @@ -134,8 +134,7 @@ public: static const char *GetInterruptName(InterruptType interrupt); static bool MatchFile(const char *haystack, int haystack_len, const std::string &needle); - static bool MatchFile(const std::string& file, const std::string& fullPath, - const std::string& relPath); + static bool MatchFile(const std::string& file, const std::string& fullPath); public: BreakPointInfo() : m_index(0) {} // for thrift diff --git a/hphp/runtime/vm/debugger_hook.cpp b/hphp/runtime/vm/debugger_hook.cpp index 1d15befec..ef5dce350 100644 --- a/hphp/runtime/vm/debugger_hook.cpp +++ b/hphp/runtime/vm/debugger_hook.cpp @@ -164,8 +164,7 @@ static void addBreakPointsInFile(Eval::DebuggerProxy* proxy, proxy->getBreakPoints(bps); for (unsigned int i = 0; i < bps.size(); i++) { Eval::BreakPointInfoPtr bp = bps[i]; - if (Eval::BreakPointInfo::MatchFile(bp->m_file, efile->getFileName(), - efile->getRelPath())) { + if (Eval::BreakPointInfo::MatchFile(bp->m_file, efile->getFileName())) { addBreakPointInUnit(bp, efile->unit()); break; } @@ -326,8 +325,9 @@ void phpSetBreakPoints(Eval::DebuggerProxy* proxy) { g_vmContext->m_evaledFiles.begin(); it != g_vmContext->m_evaledFiles.end(); ++it) { auto efile = it->second; - if (!Eval::BreakPointInfo::MatchFile(fileName, efile->getFileName(), - efile->getRelPath())) continue; + if (!Eval::BreakPointInfo::MatchFile(fileName, efile->getFileName())) { + continue; + } addBreakPointInUnit(bp, efile->unit()); break; } diff --git a/hphp/test/quick/debugger/break2.php.expectf b/hphp/test/quick/debugger/break2.php.expectf index 92157e8bb..63103fa49 100644 --- a/hphp/test/quick/debugger/break2.php.expectf +++ b/hphp/test/quick/debugger/break2.php.expectf @@ -1,7 +1,7 @@ Program %s/break2.php loaded. Type '[r]un' or '[c]ontinue' to go. -break break2.php:7 -Breakpoint 1 set on line 7 of break2.php -But wont break until file break2.php has been loaded. +break quick/debugger/break2.php:7 +Breakpoint 1 set on line 7 of quick/debugger/break2.php +But wont break until file quick/debugger/break2.php has been loaded. break foo2() Breakpoint 2 set upon entering foo2() But wont break until function foo2 has been loaded. @@ -12,7 +12,7 @@ break cls2::pubCls() Breakpoint 4 set upon entering cls2::pubCls() But wont break until class cls2 has been loaded. break list - 1 ALWAYS on line 7 of break2.php (unbound) + 1 ALWAYS on line 7 of quick/debugger/break2.php (unbound) 2 ALWAYS upon entering foo2() (unbound) 3 ALWAYS upon entering cls2::pubObj() (unbound) 4 ALWAYS upon entering cls2::pubCls() (unbound) @@ -26,12 +26,12 @@ Breakpoint 2 reached at foo2() on line 6 of %s/break2.php 7 error_log($y); break list - 1 ALWAYS on line 7 of break2.php + 1 ALWAYS on line 7 of quick/debugger/break2.php 2 ALWAYS upon entering foo2() 3 ALWAYS upon entering cls2::pubObj() 4 ALWAYS upon entering cls2::pubCls() continue -Breakpoint 1 reached at foo2() on line 7 of %s/break2.php +Breakpoint 1 reached at foo2() on line 7 of %s/quick/debugger/break2.php 6 $y = $x.'_suffix'; 7 error_log($y); 8 } diff --git a/hphp/test/quick/debugger/break2.php.in b/hphp/test/quick/debugger/break2.php.in index eb3cb8e23..55cc7f864 100644 --- a/hphp/test/quick/debugger/break2.php.in +++ b/hphp/test/quick/debugger/break2.php.in @@ -1,4 +1,4 @@ -break break2.php:7 +break quick/debugger/break2.php:7 break foo2() break cls2::pubObj() break cls2::pubCls()