The notorious reader have already noticed that there is a problem with my
suggested patch. C arrays are zero based so the length to allocate is alen+1.
A modified patch is enclosed.
/Nils
>
> As I managed to download the source I think I have located the problem. The
> current netCDF reading code maximizes the length of a character attribute
> to 128 characters. That is not very much if one wants to squeeze in both the
> name of the variables making up a series as well as the value of the series
> position in one global attribute. Further it is incorrect in the sense that
> no check was made that the read of a text attribute actually fitted in the
> space given.
>
> I made a patch to the getNattr routine in import_ncdf.c that fixes the most
> immediate problem for me. It seems to work fine and I can now read in series
> definition attributes of the length I need.
>
> There still remains a buffer over-run problem in getattr in the same source
> file. My suggestion is to fix this in the same way I did the current fix.
> That implies changes in multiple places in the file that I have not yet
> looked into what effects they will have.
>
> Anyway, for what it is worth I enclose my suggested patch below.
>
> Cheers,
>
> /Nils
>
>
>
*** import_ncdf.c-ORIG Tue Jul 17 22:37:35 2001
--- import_ncdf.c Wed Jul 18 11:43:32 2001
***************
*** 531,535 ****
int *deltatime)
{
! char stringattr[MAXNAME], *cp, *s[MAXATTRSTR], **lp;
char *subv[2];
int ndims, nvars, ngatts, recdim;
--- 531,535 ----
int *deltatime)
{
! char stringattr[MAXNAME], *cp, *s[MAXATTRSTR], **lp, *attrtext;
char *subv[2];
int ndims, nvars, ngatts, recdim;
***************
*** 563,572 ****
*/
for (k = 0; k < ngatts; k++) {
! if(!getNattr(cdfhandle, NC_GLOBAL, k, SERIESATTRIB,
! strlen(SERIESATTRIB), stringattr))
continue;
j = MAXATTRSTR;
! cp = parseit(stringattr, &j, s);
if(j <= 0) {
DXSetError(ERROR_DATA_INVALID, "bad attribute for series");
--- 563,572 ----
*/
for (k = 0; k < ngatts; k++) {
! if(!(attrtext=getNattr(cdfhandle, NC_GLOBAL, k, SERIESATTRIB,
! strlen(SERIESATTRIB), stringattr)))
continue;
j = MAXATTRSTR;
! cp = parseit(attrtext, &j, s);
if(j <= 0) {
DXSetError(ERROR_DATA_INVALID, "bad attribute for series");
***************
*** 599,603 ****
* vp3 = temp node for finding end of next->next->next chain.
*/
! if (match_vp(vp, NC_GLOBAL, s, stringattr) != NULL)
continue;
--- 599,603 ----
* vp3 = temp node for finding end of next->next->next chain.
*/
! if (match_vp(vp, NC_GLOBAL, s, attrtext) != NULL)
continue;
***************
*** 789,792 ****
--- 789,794 ----
}
count++;
+ DXFree((Pointer) attrtext);
+ attrtext=NULL;
}
***************
*** 983,986 ****
--- 985,990 ----
error:
+ if(attrtext)
+ DXFree((Pointer)attrtext);
if (found)
DXFree((Pointer)found);
***************
*** 1420,1423 ****
--- 1424,1430 ----
* complete value of the attribute, verify it is a string (char), and
* null terminate it.
+ * The attribute is returned as a newly allocated string. It is the
+ * caller's responsibility the deallocate it when it is no longer
+ * needed.
*/
static char *
***************
*** 1426,1429 ****
--- 1433,1437 ----
nc_type datatype;
int i, alen;
+ char *attrtext=NULL;
for(i = n; ; i++) {
***************
*** 1447,1455 ****
/* does this work? we are actually using the same buffer for the
* input attribute name and for the returned attribute value.
*/
! ncattget(hand, varid, attrname, stringattr);
! stringattr[alen] = '\0';
! return stringattr;
}
--- 1455,1466 ----
/* does this work? we are actually using the same buffer for the
* input attribute name and for the returned attribute value.
+ ncattget(hand, varid, attrname, stringattr);
*/
! /* No it does not. Make sure the target string has sufficient length */
! attrtext=DXAllocate(alen+1);
! ncattget(hand, varid, attrname, attrtext);
! attrtext[alen] = '\0';
! return attrtext;
}