OwnedPtr<File> DiskFile::relative(const std::string& path) { if (path.empty()) { throw std::invalid_argument("File::relative(): path cannot be empty."); } else if (path[0] == '/') { throw std::invalid_argument("File::relative(): path cannot start with a slash."); } std::string::size_type slash_pos = path.find_first_of('/'); std::string first_part; std::string rest; if (slash_pos == std::string::npos) { if (path == ".") { return clone(); } else if (path == "..") { return parent(); } else if (this->path.empty()) { return newOwned<DiskFile>(path, this); } else { return newOwned<DiskFile>(this->path + "/" + path, this); } } else { first_part.assign(path, 0, slash_pos); std::string::size_type after_slash_pos = path.find_first_not_of('/', slash_pos); if (after_slash_pos == std::string::npos) { // Trailing slash. Bah. return relative(first_part); } else { rest.assign(path, after_slash_pos, std::string::npos); if (first_part == ".") { return relative(rest); } else if (first_part == "..") { if (parentRef == NULL) { throw std::runtime_error( "Tried to get parent of top-level directory: " + canonicalName()); } return parentRef->relative(rest); } else { OwnedPtr<File> temp; if (this->path.empty()) { temp = newOwned<DiskFile>(first_part, this); } else { temp = newOwned<DiskFile>(this->path + "/" + first_part, this); } return temp->relative(rest); } } } }
// Create a new results by computing sums for equivalent names ("foo" and "foo@plt"). static Results combineLikeNames(SgAsmInterpretation *interp, const Results &separate) { // Index of functions by canonical name std::vector<SgAsmFunction*> funcList = SageInterface::querySubTree<SgAsmFunction>(interp); Map<std::string, std::vector<SgAsmFunction*> > funcMap; BOOST_FOREACH (SgAsmFunction *func, funcList) funcMap[canonicalName(func)].push_back(func); // Scan through the analysis results and sum by canonical function name Map<std::string, UsageCounts> byName; for (Results::const_iterator ri=separate.begin(); ri!=separate.end(); ++ri) byName[canonicalName(ri->first)] += ri->second; // Create a new return value for all the functions. Results retval; for (Map<std::string, UsageCounts>::iterator i=byName.begin(); i!=byName.end(); ++i) { BOOST_FOREACH (SgAsmFunction *func, funcMap[i->first]) retval[func] = i->second; } return retval; }
char *FileName::safeSearchPath(Strings *path, const char *name) { #if _WIN32 /* Disallow % / \ : and .. in name characters */ for (const char *p = name; *p; p++) { char c = *p; if (c == '\\' || c == '/' || c == ':' || c == '%' || (c == '.' && p[1] == '.')) { return NULL; } } return FileName::searchPath(path, name, 0); #elif POSIX /* Even with realpath(), we must check for // and disallow it */ for (const char *p = name; *p; p++) { char c = *p; if (c == '/' && p[1] == '/') { return NULL; } } if (path) { unsigned i; /* Each path is converted to a cannonical name and then a check is done to see * that the searched name is really a child one of the the paths searched. */ for (i = 0; i < path->dim; i++) { char *cname = NULL; char *cpath = canonicalName(path->tdata()[i]); //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", // name, (char *)path->data[i], cpath); if (cpath == NULL) goto cont; cname = canonicalName(combine(cpath, name)); //printf("FileName::safeSearchPath(): cname=%s\n", cname); if (cname == NULL) goto cont; //printf("FileName::safeSearchPath(): exists=%i " // "strncmp(cpath, cname, %i)=%i\n", exists(cname), // strlen(cpath), strncmp(cpath, cname, strlen(cpath))); // exists and name is *really* a "child" of path if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) { free(cpath); char *p = mem.strdup(cname); free(cname); return p; } cont: if (cpath) free(cpath); if (cname) free(cname); } } return NULL; #else assert(0); #endif }
const char *FileName::safeSearchPath(Strings *path, const char *name) { #if _WIN32 // don't allow leading / because it might be an absolute // path or UNC path or something we'd prefer to just not deal with if (*name == '/') { return NULL; } /* Disallow % \ : and .. in name characters * We allow / for compatibility with subdirectories which is allowed * on dmd/posix. With the leading / blocked above and the rest of these * conservative restrictions, we should be OK. */ for (const char *p = name; *p; p++) { char c = *p; if (c == '\\' || c == ':' || c == '%' || (c == '.' && p[1] == '.')) { return NULL; } } return FileName::searchPath(path, name, false); #elif POSIX /* Even with realpath(), we must check for // and disallow it */ for (const char *p = name; *p; p++) { char c = *p; if (c == '/' && p[1] == '/') { return NULL; } } if (path) { /* Each path is converted to a cannonical name and then a check is done to see * that the searched name is really a child one of the the paths searched. */ for (size_t i = 0; i < path->dim; i++) { const char *cname = NULL; const char *cpath = canonicalName((*path)[i]); //printf("FileName::safeSearchPath(): name=%s; path=%s; cpath=%s\n", // name, (char *)path->data[i], cpath); if (cpath == NULL) goto cont; cname = canonicalName(combine(cpath, name)); //printf("FileName::safeSearchPath(): cname=%s\n", cname); if (cname == NULL) goto cont; //printf("FileName::safeSearchPath(): exists=%i " // "strncmp(cpath, cname, %i)=%i\n", exists(cname), // strlen(cpath), strncmp(cpath, cname, strlen(cpath))); // exists and name is *really* a "child" of path if (exists(cname) && strncmp(cpath, cname, strlen(cpath)) == 0) { ::free(const_cast<char *>(cpath)); const char *p = mem.xstrdup(cname); ::free(const_cast<char *>(cname)); return p; } cont: if (cpath) ::free(const_cast<char *>(cpath)); if (cname) ::free(const_cast<char *>(cname)); } } return NULL; #else assert(0); #endif }
OwnedPtr<File> DiskFile::parent() { if (parentRef == NULL) { throw std::runtime_error("Tried to get parent of top-level directory: " + canonicalName()); } return parentRef->clone(); }