Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
On Dec 19, 2010, at 1:09 PM, Alan W. Irwin wrote: > Dave, do you see any downsides > to the above idea as I have fleshed it out? Only the ones I outlined earlier in this thread... On Dec 18, 2010, at 11:34 AM, David MacMahon wrote: > I think automatic allocation by the library function, while not a big > drawback, has a few potential points against it. One it that memory > allocation is one of the (potentially) more expensive operations, so > minimizing it is desirable. I don't think the use cases in question will > result in this being a significant factor. The other issue is that once the > library has allocated and populated the buffer, language bindings sometimes > (typically?) require that the contents be copied into a suitably sized buffer > that the scripting language manages. In this case the result is a double > allocation (one by the library function, one by the scripting language), a > extra strcpy from library buffer to scripting language buffer, and a free of > the buffer returned by the library function. > > Getting the size first, allocating a buffer using he scripting language > memory management routines, then passing the pointer to the library routine > is, IMHO, more cleanly amenable to scripting language bindings (though I > write mine "manually" so I don't know whether this would apply to SWIG > generated bindings). > > Again, I don't think these factors will be significant for the functions > under discussion, so I'll be happy with whatever consensus emerges. Dave -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
Hi Dave (with a question for Andrew at the end): > On Dec 18, 2010, at 6:30 PM, Alan W. Irwin wrote: >> With plgnfnam that would be changed to something like >> >> (needed_size, fnam) = plgnfnam(100) >> if needed_size >= 100: >> # Oops, 100 was too small. >> fname = plgnfnam(needed_size+1)[1] > > This is an example of why I like to hand code language bindings. IMHO, the plgnfnam function, if it is even exposed in the scripting language, should take no arguments and always return a string containing the entire contents. Why make the user provide an initial guess? This requires them to check whether their guess was big enough and try again (without forgetting the "+1") if it wasn't. How inconvenient! Good points. Hiding details is always good so I think we should do this. So far I think we are in consensus, but now I have had one more thought that would change the proposed API to be quite different than strlcpy. (Sorry about that!) That thought is if information hiding is good for high-level languages, why not do that at the C level right from the start? In other words, after this large sidetrack I have come to the conclusion that we should use Andrew's idea to alloc sufficient space inside plgnfnam, etc. to hold the string. After all, we can use strlen to determine the lengths of the version, device, and filename strings for a particular stream so allocing inside the routines with the exact size required seems like a good idea to me with no worries about initial guesses for the size, reallocating, etc. So the API would look like the following (dropping n from the name with its mental association with a size argument and putting a 1 on the end instead to differentiate this new set of routines from the deprecated versions): char * plgfnam1(void); So a typical use fragment would be the following. (I hope I have gotten this right because I still often screw up C pointers due to my lack of experience with C other than my contributions to PLplot). char * fnam; fnam = (char *) plgfname1(); fprintf( stdout, "PLplot file name: %s\n", fnam ); free(fnam); And for Python, the call would be fnam = plgfnam1() or fnam = plgfnam() (which would be exactly equivalent to plgfnam1) with all details about the C level call to plgfnam1() and freeing the buffer after the string is copied to the Python level hidden in the swig-generated interface. And similarly for the other high-level languages. Andrew, is that what you had in mind from the get go? Dave, do you see any downsides to the above idea as I have fleshed it out? Alan __ Alan W. Irwin Astronomical research affiliation with Department of Physics and Astronomy, University of Victoria (astrowww.phys.uvic.ca). Programming affiliations with the FreeEOS equation-of-state implementation for stellar interiors (freeeos.sf.net); PLplot scientific plotting software package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of Linux Links project (loll.sf.net); and the Linux Brochure Project (lbproject.sf.net). __ Linux-powered Science __ -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
On Dec 18, 2010, at 6:30 PM, Alan W. Irwin wrote: > On 2010-12-18 11:34-0800 David MacMahon wrote: > >> Am I missing something? > > See their example 1d where they check for truncation. Instead of > taking an error return at that point as they did in their sample code > the user could instead realloc if they liked as in your original > suggestion. Thanks, I did miss something! :-) The strlcpy model seems very similar to the WIN32 convention, only better in that it is more rigorously documented vis-a-vis NUL termination. > Just because it appears to be better documented on the > null-termination guarantee issue, I suggest we adopt the strlcpy > model. This gives the user in any language freedom to do anything > they like if the returned size (which never counts the null > terminator) is >= the value of n in the call. I agree! > For high-level languages > like Python where the uses don't have to worry about allocation, they > could just call the function again with n chosen to be the previous > returned value + 1. For high level languages like Python, any (re-)allocation could happen in the bindings and therefore be hidden from the end user. > Also, I don't think we should use the wrinkle present in > GetShortPathName of doing something special for the NULL buffer, > size=0 call. That does add a bit of convenience (but is not a > necessity) for languages such as C where the buffer is alloced > beforehand, I agree about not treating a NULL pointer as a special case, but strlcpy inherently treats size=0 as a special case (i.e. no NUL terminator). When size=0, strlcpy ignores the pointer and gives the same result as the WIN32 convention (though the WIN32 convention requires the pointer to be NULL). > but that wrinkle makes no sense for higher level languages > such as Python where the correctly sized buffer is created as needed. > For example, a typical Python call to plgfnam is > > fnam = plgfnam() > > With plgnfnam that would be changed to something like > > (needed_size, fnam) = plgnfnam(100) > if needed_size >= 100: > # Oops, 100 was too small. > fname = plgnfnam(needed_size+1)[1] This is an example of why I like to hand code language bindings. IMHO, the plgnfnam function, if it is even exposed in the scripting language, should take no arguments and always return a string containing the entire contents. Why make the user provide an initial guess? This requires them to check whether their guess was big enough and try again (without forgetting the "+1") if it wasn't. How inconvenient! Why not just do all of that for them inside the bindings for the high-level language's plgfnam call (which would call plgnfnam under the covers)? Dave -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
On 2010-12-18 11:34-0800 David MacMahon wrote: > Hi, Alan, > > On Dec 18, 2010, at 10:57 AM, Alan W. Irwin wrote: > >> Another model for plgnver, plgndev, and plgnfnam is one similar to >> strlcpy that is discussed by Todd C. Miller and Theo de Raadt at >> http://www.gratisoft.us/todd/papers/strlcpy.html. That is a most >> interesting paper to read. I am not necessarily advocating something >> similar to this model API. I leave that to those more knowledgable in >> C than I am. However, I am mentioning this paper for further >> discussion. > > It seems like strlcpy is a more convenient alternative to strncpy, but I don't see how this would solve the allocation problem. Wouldn't the user still need to ensure that a large enough buffer has been allocated? If so, the problem of determining how large is large enough still remains. Am I missing something? See their example 1d where they check for truncation. Instead of taking an error return at that point as they did in their sample code the user could instead realloc if they liked as in your original suggestion. Of course, the real value of the strlcpy model is the thought that has gone into the null termination issue as well as the definition of the size of the buffer that is returned. For example, after much debate about the alternatives they decided to use the snprintf return semantics, that is, the returned length does not include the null terminator which is the same definition as the string length calculated by strlen. N.B. I have now found an additional useful reference for strlcpy which is http://www.manpagez.com/man/3/strlcpy/ > >> Can you remember the name of the function you were using as >> the model >> for your API suggestion for plgnver, plgndev, and plgnfnam? If so, >> that will give us a chance to dig into the official documention of >> that function like we can currently do for getcwd and strlcpy. > Dave> > > OK, digging way back into my mental archives (and googling), I think I first came across this approach in a previous life when I did Windows programming. An example of this approach can be seen in the Windows GetShortPathName function (and probably others as well)... > > http://msdn.microsoft.com/en-us/library/aa364989(v=vs.85).aspx > > I mis-remembered the exact details of the return code. The WIN32 functions seem to return the total size needed iff the buffer pointer is NULL and the size is given as 0. This shouldn't really change the fundamentals of what I wrote earlier, however. Thanks for that reference. However, I have noticed some deficiencies in that documentation of GetShortPathName. There is no mention there of null termination guaranteed in the result which is an important issue covered in the strlcpy documentation. For example, what happens if the buffer receiving the result is too small? Do you get a truncated result with no null terminator or a truncated result of one unit smaller in size followed by a null terminator, or nothing at all in the result? Just because it appears to be better documented on the null-termination guarantee issue, I suggest we adopt the strlcpy model. This gives the user in any language freedom to do anything they like if the returned size (which never counts the null terminator) is >= the value of n in the call. For high-level languages like Python where the uses don't have to worry about allocation, they could just call the function again with n chosen to be the previous returned value + 1. For lower-level languages like C, they could realloc the buffer using the correct size, return an error, or just accept the truncated result. Also, I don't think we should use the wrinkle present in GetShortPathName of doing something special for the NULL buffer, size=0 call. That does add a bit of convenience (but is not a necessity) for languages such as C where the buffer is alloced beforehand, but that wrinkle makes no sense for higher level languages such as Python where the correctly sized buffer is created as needed. For example, a typical Python call to plgfnam is fnam = plgfnam() With plgnfnam that would be changed to something like (needed_size, fnam) = plgnfnam(100) if needed_size >= 100: # Oops, 100 was too small. fname = plgnfnam(needed_size+1)[1] On the other hand, I would hope the PLplot version or device names are unlikely to be greater than 20 characters in our lifetimes. So for that case, you normally wouldn't bother to check the needed size in Python: version = plgnfnam(20)[1] devname = plgndev(20)[1] Note, even in the unlikely case that the version or device name were greater than 20 characters, the above calls would be perfectly safe and would yield properly truncated results at the 20th character. Alan __ Alan W. Irwin Astronomical research affiliation with Department of Physics and Astronomy, University of Victoria (astrowww.phys.uvic.ca). Programming affiliations with the FreeEOS equation-of-state implementation for
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
Hi, Alan, On Dec 18, 2010, at 10:57 AM, Alan W. Irwin wrote: > Another model for plgnver, plgndev, and plgnfnam is one similar to > strlcpy that is discussed by Todd C. Miller and Theo de Raadt at > http://www.gratisoft.us/todd/papers/strlcpy.html. That is a most > interesting paper to read. I am not necessarily advocating something > similar to this model API. I leave that to those more knowledgable in > C than I am. However, I am mentioning this paper for further > discussion. It seems like strlcpy is a more convenient alternative to strncpy, but I don't see how this would solve the allocation problem. Wouldn't the user still need to ensure that a large enough buffer has been allocated? If so, the problem of determining how large is large enough still remains. Am I missing something? > Can you remember the name of the function you were using as > the model > for your API suggestion for plgnver, plgndev, and plgnfnam? If so, > that will give us a chance to dig into the official documention of > that function like we can currently do for getcwd and strlcpy. Dave> OK, digging way back into my mental archives (and googling), I think I first came across this approach in a previous life when I did Windows programming. An example of this approach can be seen in the Windows GetShortPathName function (and probably others as well)... http://msdn.microsoft.com/en-us/library/aa364989(v=vs.85).aspx I mis-remembered the exact details of the return code. The WIN32 functions seem to return the total size needed iff the buffer pointer is NULL and the size is given as 0. This shouldn't really change the fundamentals of what I wrote earlier, however. > On 2010-12-18 13:59- Andrew Ross wrote: > >> Down side for us [of automatic allocation] is that allocated memory >> in C may be difficult to use in other languages. I think automatic allocation by the library function, while not a big drawback, has a few potential points against it. One it that memory allocation is one of the (potentially) more expensive operations, so minimizing it is desirable. I don't think the use cases in question will result in this being a significant factor. The other issue is that once the library has allocated and populated the buffer, language bindings sometimes (typically?) require that the contents be copied into a suitably sized buffer that the scripting language manages. In this case the result is a double allocation (one by the library function, one by the scripting language), a extra strcpy from library buffer to scripting language buffer, and a free of the buffer returned by the library function. Getting the size first, allocating a buffer using he scripting language memory management routines, then passing the pointer to the library routine is, IMHO, more cleanly amenable to scripting language bindings (though I write mine "manually" so I don't know whether this would apply to SWIG generated bindings). Again, I don't think these factors will be significant for the functions under discussion, so I'll be happy with whatever consensus emerges. Dave -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
Hi Andrew (with one question for Dave): Thanks for contributing to this discussion. On 2010-12-18 13:59- Andrew Ross wrote: > I think passing a buffer size is the safest way to go. If you wanted a > constant buffer length, then it should be PATH_MAX to ensure any path > will fit, but this still has risks associated. Agreed. > > Note other functions (e.g. getcwd - Linux extension) interpret a null > buffer differently, and will allocate a buffer using malloc in this > case to allocate a buffer. If the buffer size parameter > 0 then the > allocated buffer is of that size. If if is zero then a buffer big > enough to return the path is allocated. Note getcwd also returns null > if the buffer is not big enough and sets errno to ERANGE. > > I'm not necessarily suggesting this is better, but it an alternative > approach. Plus side is that it is easier for the user - allocations > are done automatically. Another model for plgnver, plgndev, and plgnfnam is one similar to strlcpy that is discussed by Todd C. Miller and Theo de Raadt at http://www.gratisoft.us/todd/papers/strlcpy.html. That is a most interesting paper to read. I am not necessarily advocating something similar to this model API. I leave that to those more knowledgable in C than I am. However, I am mentioning this paper for further discussion. Can you remember the name of the function you were using as the model for your API suggestion for plgnver, plgndev, and plgnfnam? If so, that will give us a chance to dig into the official documention of that function like we can currently do for getcwd and strlcpy. > Down side for us [of automatic allocation] is that allocated memory > in C may be difficult to use in other languages. Unless I misunderstood you, I think that allocation, possible reallocation, and free of a C buffer is a given (which I like) for all approaches discussed so far. For example, this is true for the getcwd Linux extension approach, the strlcpy approach, or Dave's approach. After the C buffer is filled with the character-string information from the PLplot core library, then it is up to each language interface to pass that information on to the language environment in appropriate form. That seems to be the model used in our swig-based language bindings and also for Tcl (if I am following that generated code correctly). My guess is our remaining language bindings follow that model as well. Regardless, they all currently implement plgver, plgdev, and plgfnam without issues so that means it should be possible to adapt those approaches to the plgnver, plgndev, and plgnfnam cases once we finalize the API for those. Alan __ Alan W. Irwin Astronomical research affiliation with Department of Physics and Astronomy, University of Victoria (astrowww.phys.uvic.ca). Programming affiliations with the FreeEOS equation-of-state implementation for stellar interiors (freeeos.sf.net); PLplot scientific plotting software package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of Linux Links project (loll.sf.net); and the Linux Brochure Project (lbproject.sf.net). __ Linux-powered Science __ -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
On Fri, Dec 17, 2010 at 10:53:44AM -0800, Alan Irwin wrote: > On 2010-12-16 21:15-0800 David MacMahon wrote: > > > Hi, Alan, > > > > On Dec 16, 2010, at 6:54 PM, Alan W. Irwin wrote: > > > >> Here is what I propose instead of this temporary measure. We go with > >> a backward-incompatible API change (and associated soname bump to > >> force everybody to recompile) of > >> > >> c_plgfnam( char *fnam ); ==> c_plgfnam( char *fnam, PLINT n); > >> > >> where n is the size of the buffer that has been allocated. > >> Internally, c_plgfnam will use n for the strncpy call as well as > >> figuring out the last byte to zero. > >> > >> Note, the other two PLplot functions (plgver and plgdev) that return > >> character strings have recommendations in the documentation to > >> allocate 80-byte buffers to contain the version string and device > >> name. > > > > > I notice that all of these functions currently have a null return > type. One approach I've seen elsewhere, is to have functions like > this return an int indicating how many bytes were copied into the > buffer if the pointer given is non-null *or*, if the given pointer is > null, how many more bytes are needed to fill the buffer. > > > This allows the client code to determine the buffer size needed, > (re-)allocate the buffer dynamically, then fill the buffer... > > > > > bufsize = plgver(NULL, 0); > > buf = (char *)malloc(bufsize+1); > > plgver(buf, bufsize); > > buf[bufsize] = '\0'; > > > > // Note how this can be used to determine > > // whether a buffer is already big enough > > > > extra = plgfnam(NULL, bufsize); > > if(extra > 0) { > > buf = (char *)realloc(buf, bufsize+extra+1); > > } > > bufsize += extra; > > > > // if extra < 0, bufsize will be smaller > > // than size of region allocated > > plgfnam(buf, bufsize); > > buf[bufsize] = '\0'; > > I very much like the general idea of using a returned value to always > allow changing the buffer size as appropriate. So many thanks for > bringing up this possibility, and I hope the result is we handle > these buffer size issues in an absolutely ideal way. > > Furthermore, I have now changed my mind about two matters I discussed in > my previous post. > > I now think we should prevent the soname bump (for now) by simply > deprecating plgver, plgdev, and plgfnam and adding new functions > called plgnver, plgndev, and plgnfnam that handle the buffer size > issue in an ideal way. My original thought was we wouldn't need > plgnver and plgndev. But now I think we do just based on the > interests of uniformity. I think passing a buffer size is the safest way to go. If you wanted a constant buffer length, then it should be PATH_MAX to ensure any path will fit, but this still has risks associated. Note other functions (e.g. getcwd - Linux extension) interpret a null buffer differently, and will allocate a buffer using malloc in this case to allocate a buffer. If the buffer size parameter > 0 then the allocated buffer is of that size. If if is zero then a buffer big enough to return the path is allocated. Note getcwd also returns null if the buffer is not big enough and sets errno to ERANGE. I'm not necessarily suggesting this is better, but it an alternative approach. Plus side is that it is easier for the user - allocations are done automatically. Down side for us is that allocated memory in C may be difficult to use in other languages. > > Of course, propagation of this new plgnver, plgndev, and plgnfnam > functionality to some languages might be tricky. I checked that for > our swig-based languages (Python, Java, and Lua), and I don't think it > will be a problem for that case. swig allows inserting arbitrary C > code such as the above allocs or reallocs into the interface. And it > is obviously not a problem to implement the new functionality in our > C++ language bindings. However, I would like all the language gurus > to think about implementing this new functionality for their favorite > language such as Ada (Jerry), D (Werner), Fortran 77, Fortran 95, and > Tcl (Arjen), OCaml (Hez), Octave (Andrew), and the externally > developed perl/PDL bindings (Doug Hunt who also lurks here). Andrew -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
On 2010-12-16 21:15-0800 David MacMahon wrote: > Hi, Alan, > > On Dec 16, 2010, at 6:54 PM, Alan W. Irwin wrote: > >> Here is what I propose instead of this temporary measure. We go with >> a backward-incompatible API change (and associated soname bump to >> force everybody to recompile) of >> >> c_plgfnam( char *fnam ); ==> c_plgfnam( char *fnam, PLINT n); >> >> where n is the size of the buffer that has been allocated. >> Internally, c_plgfnam will use n for the strncpy call as well as >> figuring out the last byte to zero. >> >> Note, the other two PLplot functions (plgver and plgdev) that return >> character strings have recommendations in the documentation to >> allocate 80-byte buffers to contain the version string and device >> name. > > I notice that all of these functions currently have a null return type. One approach I've seen elsewhere, is to have functions like this return an int indicating how many bytes were copied into the buffer if the pointer given is non-null *or*, if the given pointer is null, how many more bytes are needed to fill the buffer. > This allows the client code to determine the buffer size needed, (re-)allocate the buffer dynamically, then fill the buffer... > > bufsize = plgver(NULL, 0); > buf = (char *)malloc(bufsize+1); > plgver(buf, bufsize); > buf[bufsize] = '\0'; > > // Note how this can be used to determine > // whether a buffer is already big enough > > extra = plgfnam(NULL, bufsize); > if(extra > 0) { > buf = (char *)realloc(buf, bufsize+extra+1); > } > bufsize += extra; > > // if extra < 0, bufsize will be smaller > // than size of region allocated > plgfnam(buf, bufsize); > buf[bufsize] = '\0'; I very much like the general idea of using a returned value to always allow changing the buffer size as appropriate. So many thanks for bringing up this possibility, and I hope the result is we handle these buffer size issues in an absolutely ideal way. Furthermore, I have now changed my mind about two matters I discussed in my previous post. I now think we should prevent the soname bump (for now) by simply deprecating plgver, plgdev, and plgfnam and adding new functions called plgnver, plgndev, and plgnfnam that handle the buffer size issue in an ideal way. My original thought was we wouldn't need plgnver and plgndev. But now I think we do just based on the interests of uniformity. Of course, propagation of this new plgnver, plgndev, and plgnfnam functionality to some languages might be tricky. I checked that for our swig-based languages (Python, Java, and Lua), and I don't think it will be a problem for that case. swig allows inserting arbitrary C code such as the above allocs or reallocs into the interface. And it is obviously not a problem to implement the new functionality in our C++ language bindings. However, I would like all the language gurus to think about implementing this new functionality for their favorite language such as Ada (Jerry), D (Werner), Fortran 77, Fortran 95, and Tcl (Arjen), OCaml (Hez), Octave (Andrew), and the externally developed perl/PDL bindings (Doug Hunt who also lurks here). Alan __ Alan W. Irwin Astronomical research affiliation with Department of Physics and Astronomy, University of Victoria (astrowww.phys.uvic.ca). Programming affiliations with the FreeEOS equation-of-state implementation for stellar interiors (freeeos.sf.net); PLplot scientific plotting software package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of Linux Links project (loll.sf.net); and the Linux Brochure Project (lbproject.sf.net). __ Linux-powered Science __ -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
Re: [Plplot-devel] Fix for 79-character truncation on plgfnam
Hi, Alan, On Dec 16, 2010, at 6:54 PM, Alan W. Irwin wrote: > Here is what I propose instead of this temporary measure. We go with > a backward-incompatible API change (and associated soname bump to > force everybody to recompile) of > > c_plgfnam( char *fnam ); ==> c_plgfnam( char *fnam, PLINT n); > > where n is the size of the buffer that has been allocated. > Internally, c_plgfnam will use n for the strncpy call as well as > figuring out the last byte to zero. > > Note, the other two PLplot functions (plgver and plgdev) that return > character strings have recommendations in the documentation to > allocate 80-byte buffers to contain the version string and device > name. I notice that all of these functions currently have a null return type. One approach I've seen elsewhere, is to have functions like this return an int indicating how many bytes were copied into the buffer if the pointer given is non-null *or*, if the given pointer is null, how many more bytes are needed to fill the buffer. This allows the client code to determine the buffer size needed, (re-)allocate the buffer dynamically, then fill the buffer... bufsize = plgver(NULL, 0); buf = (char *)malloc(bufsize+1); plgver(buf, bufsize); buf[bufsize] = '\0'; // Note how this can be used to determine // whether a buffer is already big enough extra = plgfnam(NULL, bufsize); if(extra > 0) { buf = (char *)realloc(buf, bufsize+extra+1); } bufsize += extra; // if extra < 0, bufsize will be smaller // than size of region allocated plgfnam(buf, bufsize); buf[bufsize] = '\0'; Just an idea, Dave -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel
[Plplot-devel] Fix for 79-character truncation on plgfnam
Andrew, I would very much appreciate your and other PLplot API expert's comments on this issue. I noticed during some of my generic testing today that the output file name was truncated for the 31st example at the 79th character. This seems to be a rather tight limit for today's computers where full pathnames of files can reach far beyond 79 characters. Accordingly I have replaced (revision 11375) all occurrences of 80 by 256 in examples/*/*31* and changed plgfnam internally so that it truncates at the 255th character. The result works, but I view this internal change to plgfnam as a dangerous temporary measure because those who stick with the old limit of 80-byte buffers for their plgfnam calls will have a guaranteed buffer overflow because the revised plgfnam puts a "\0" in the 256th byte of the buffer. Here is what I propose instead of this temporary measure. We go with a backward-incompatible API change (and associated soname bump to force everybody to recompile) of c_plgfnam( char *fnam ); ==> c_plgfnam( char *fnam, PLINT n); where n is the size of the buffer that has been allocated. Internally, c_plgfnam will use n for the strncpy call as well as figuring out the last byte to zero. Note, the other two PLplot functions (plgver and plgdev) that return character strings have recommendations in the documentation to allocate 80-byte buffers to contain the version string and device name. That recommendation should be entirely safe for the forseeable future. Note it is only a recommendation and inside those routines that limit is not enforced. However, plgfnam is quite different. The 80-byte buffer limit there is recommended and also enforced internally by the implementation (before the above commit). That caused truncated filename results to be returned whenever the length of the full pathnames of files used by file device drivers exceeded 79 bytes. I need comments and discussion by our API experts here to make sure the proposed backwards-incompatible change to the plgfnam API is the way to go. Alan __ Alan W. Irwin Astronomical research affiliation with Department of Physics and Astronomy, University of Victoria (astrowww.phys.uvic.ca). Programming affiliations with the FreeEOS equation-of-state implementation for stellar interiors (freeeos.sf.net); PLplot scientific plotting software package (plplot.org); the libLASi project (unifont.org/lasi); the Loads of Linux Links project (loll.sf.net); and the Linux Brochure Project (lbproject.sf.net). __ Linux-powered Science __ -- Lotusphere 2011 Register now for Lotusphere 2011 and learn how to connect the dots, take your collaborative environment to the next level, and enter the era of Social Business. http://p.sf.net/sfu/lotusphere-d2d ___ Plplot-devel mailing list Plplot-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/plplot-devel