dromodel
dromodel

Reputation: 10203

What is the safe alternative to realpath()?

I am working on a program which uses realpath() to get the absolute path of a file. Unfortunately, this function takes a string buffer that is expected to be so large that it is big enough and that's not safe when this application has to run across multiple platforms. Is there a safe version of this function which avoids the buffer overflow issue, perhaps using dynamic memory allocation?

Upvotes: 17

Views: 23623

Answers (3)

Yuriy Petrovskiy
Yuriy Petrovskiy

Reputation: 8178

There is a way to do the same in Boost using boost::filesystem:

#include <boost/filesystem.hpp>

using namespace boost::filesystem;

try{
    path absolutePath = canonical("./../xxx"); //will throw exception if file not exists!

}
catch{...}{
    cout << "File not exists";
}
cout << absolutePath.string(); 

There is QT way to do it (got from here):

QFileInfo target_file_name(argv[1]);
QString absolute_path = target_file_name.absolutePath() 

There is a bit complicated implementation of realpath in C++. Cannot tell anything about it's safety, but it should allow path with length more then PATH_MAX. Going to test it soon.

Upvotes: 2

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215261

See here for information on safe and portable use of realpath:

http://www.opengroup.org/onlinepubs/9699919799/functions/realpath.html

Basically, modern standards allow you to pass a NULL pointer, and realpath will allocate a buffer of the appropriate length. If you want to be portable to legacy systems which do not support this standard, simply check #ifdef PATH_MAX and use a fixed-size buffer of length PATH_MAX. As far as I know, there are no legacy systems that lack a constant PATH_MAX but which do not support NULL arguments to realpath.

Upvotes: 20

Evan Teran
Evan Teran

Reputation: 90422

From the manpage:

If resolved_path is specified as NULL, then realpath() uses malloc(3) to allocate a buffer of up to PATH_MAX bytes to hold the resolved pathname, and returns a pointer to this buffer. The caller should deallocate this buffer using free(3).buffer using free(3).

So it seems like you can just do this:

char *real_path = realpath(path, NULL);
// use real_path
free(real_path);

Upvotes: 14

Related Questions