Skip to content

Commit

Permalink
Merge pull request #1989 from DennisHeimbigner/shellfix.dmh
Browse files Browse the repository at this point in the history
Fix shell handling of escapes
  • Loading branch information
WardF committed Apr 22, 2021
2 parents 67c640f + 2bdc00c commit 706e33b
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 11 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Expand Up @@ -6,6 +6,7 @@ Release Notes {#RELEASE_NOTES}
This file contains a high-level description of this package's evolution. Releases are in reverse chronological order (most recent first). Note that, as of netcdf 4.2, the `netcdf-c++` and `netcdf-fortran` libraries have been separated into their own libraries.
## 4.8.1 - TBD

* [Bug Fix] Fix hack for handling failure of shell programs to properly handle escape characters. See [Github #1989](https://github.com/Unidata/netcdf-c/issues/1989).
* [Bug Fix] Allow some primitive type names to be used as identifiers depending on the file format. See [Github #1984](https://github.com/Unidata/netcdf-c/issues/1984).
* [Enhancement] Add support for reading/writing pure Zarr storage format that supports the XArray _ARRAY_DIMENSIONS attribute. See [Github #1952](https://github.com/Unidata/netcdf-c/pull/1952) for more information.
* [Update] Updated version of bzip2 used in filter testing/functionality, in support of [Github #1969](https://github.com/Unidata/netcdf-c/issues/1969).
Expand Down
1 change: 1 addition & 0 deletions include/ncpathmgr.h
Expand Up @@ -168,5 +168,6 @@ EXTERNL void printutf8hex(const char* s, char* sx);
/* From dutil.c */
EXTERNL char* NC_backslashEscape(const char* s);
EXTERNL char* NC_backslashUnescape(const char* esc);
EXTERNL char* NC_shellUnescape(const char* esc);

#endif /* _NCPATHMGR_H_ */
32 changes: 32 additions & 0 deletions libdispatch/dutil.c
Expand Up @@ -164,6 +164,37 @@ NC_entityescape(const char* s)
return escaped;
}

char*
/*
Depending on the platform, the shell will sometimes
pass an escaped octotherpe character without removing
the backslash. So this function is appropriate to be called
on possible url paths to unescape such cases. See e.g. ncgen.
*/
NC_shellUnescape(const char* esc)
{
size_t len;
char* s;
const char* p;
char* q;

if(esc == NULL) return NULL;
len = strlen(esc);
s = (char*)malloc(len+1);
if(s == NULL) return NULL;
for(p=esc,q=s;*p;) {
switch (*p) {
case '\\':
if(p[1] == '#')
p++;
/* fall thru */
default: *q++ = *p++; break;
}
}
*q = '\0';
return s;
}

/**
Wrap mktmp and return the generated path,
or null if failed.
Expand Down Expand Up @@ -371,3 +402,4 @@ int isnan(double x)
}

#endif /*APPLE*/

4 changes: 2 additions & 2 deletions ncdump/nccopy.c
Expand Up @@ -2412,8 +2412,8 @@ main(int argc, char**argv)
error("one input file and one output file required");
}
/* Canonicalize the input and output files names */
inputfile = NC_backslashUnescape(argv[0]); /* Remove shell added escapes */
outputfile = NC_backslashUnescape(argv[1]);
inputfile = NC_shellUnescape(argv[0]); /* Remove shell added escapes */
outputfile = NC_shellUnescape(argv[1]);
if(strcmp(inputfile, outputfile) == 0) {
error("output would overwrite input");
}
Expand Down
2 changes: 1 addition & 1 deletion ncdump/ncdump.c
Expand Up @@ -2335,7 +2335,7 @@ main(int argc, char *argv[])

/* We need to look for escape characters because the argument
may have come in via a shell script */
path = NC_backslashUnescape(argv[i]);
path = NC_shellUnescape(argv[i]);
if(path == NULL) {
snprintf(errmsg,sizeof(errmsg),"out of memory un-escaping argument %s", argv[i]);
goto fail;
Expand Down
4 changes: 2 additions & 2 deletions ncgen/main.c
Expand Up @@ -351,7 +351,7 @@ main(
break;
case 'o': /* to explicitly specify output name */
if(netcdf_name) efree(netcdf_name);
netcdf_name = NC_backslashUnescape(optarg);
netcdf_name = NC_shellUnescape(optarg);
break;
case 'P': /* diskless with persistence */
diskless = 1;
Expand Down Expand Up @@ -460,7 +460,7 @@ main(
}
}

cdlname = NC_backslashUnescape(argv[0]);
cdlname = NC_shellUnescape(argv[0]);
if(cdlname != NULL) {
if(strlen(cdlname) > NC_MAX_NAME)
cdlname[NC_MAX_NAME] = '\0';
Expand Down
2 changes: 1 addition & 1 deletion nczarr_test/ncdumpchunks.c
Expand Up @@ -485,7 +485,7 @@ main(int argc, char** argv)
}

{
char* s = NC_backslashUnescape(argv[0]);
char* s = NC_shellUnescape(argv[0]);
strcpy(format.file_name,filenamefor(s));
nullfree(s);
}
Expand Down
2 changes: 1 addition & 1 deletion nczarr_test/s3util.c
Expand Up @@ -163,7 +163,7 @@ main(int argc, char** argv)
dumpoptions.nctype = typefor(optarg);
break;
case 'u': {
char* p = NC_backslashUnescape(optarg);
char* p = NC_shellUnescape(optarg);
ncuriparse(p,&dumpoptions.url);
nullfree(p);
if(dumpoptions.url == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion nczarr_test/tst_utils.c
Expand Up @@ -129,7 +129,7 @@ getoptions(int* argcp, char*** argvp)
*argvp += optind;

if(*argcp > 0) {
char* p = NC_backslashUnescape((*argvp)[0]);
char* p = NC_shellUnescape((*argvp)[0]);
strcpy(options->file,filenamefor(p));
nullfree(p);
}
Expand Down
2 changes: 1 addition & 1 deletion nczarr_test/zmapio.c
Expand Up @@ -177,7 +177,7 @@ main(int argc, char** argv)
}

{
char* p = NC_backslashUnescape(argv[0]);
char* p = NC_shellUnescape(argv[0]);
strcpy(dumpoptions.infile,filenamefor(p));
if(p) free(p);
}
Expand Down
10 changes: 8 additions & 2 deletions unit_test/test_pathcvt.c
Expand Up @@ -27,6 +27,7 @@ typedef struct Test {
static Test PATHTESTS[] = {
{"/xxx/a/b",{"/xxx/a/b", "/c/xxx/a/b", "/cygdrive/c/xxx/a/b", "c:\\xxx\\a\\b"}},
{"d:/x/y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
{"d:\\x\\y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
{"/cygdrive/d/x/y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
{"/d/x/y",{ "/d/x/y", "/d/x/y", "/cygdrive/d/x/y", "d:\\x\\y"}},
{"/cygdrive/d",{ "/d", "/d", "/cygdrive/d", "d:"}},
Expand All @@ -38,6 +39,7 @@ static Test PATHTESTS[] = {
"d:\\git\\netcdf-c\\dap4_test\\test_anon_dim.2.syn"}},
/* Test relative path */
{"x/y",{ "x/y", "x/y", "x/y", "x\\y"}},
{"x\\y",{ "x/y", "x/y", "x/y", "x\\y"}},
#ifndef _WIN32
/* Test utf8 path */
{"/海/海",{ "/海/海", "/c/海/海", "/cygdrive/c/海/海", "c:\\海\\海"}},
Expand All @@ -54,6 +56,7 @@ main(int argc, char** argv)
Test* test;
int failcount = 0;
char* cvt = NULL;
char* unescaped = NULL;
int k;
int drive = 'c';

Expand All @@ -71,7 +74,9 @@ main(int argc, char** argv)
#endif
continue;
}
cvt = NCpathcvt_test(test->test,kind,drive);
/* ensure that NC_shellUnescape does not affect result */
unescaped = NC_shellUnescape(test->test);
cvt = NCpathcvt_test(unescaped,kind,drive);
#ifdef DEBUG
fprintf(stderr,"TEST local=%s: input: |%s| expected=|%s| actual=|%s|: ",
kind2string(kind),test->test,test->expected[k],cvt);
Expand All @@ -95,10 +100,11 @@ main(int argc, char** argv)
#ifdef DEBUG
fprintf(stderr,"\n");
#endif
nullfree(unescaped); unescaped = NULL;
nullfree( cvt); cvt = NULL;
}
}
nullfree(cvt);
nullfree(cvt); nullfree(unescaped);
fprintf(stderr,"%s test_pathcvt\n",failcount > 0 ? "***FAIL":"***PASS");
nc_finalize();
return (failcount > 0 ? 1 : 0);
Expand Down

0 comments on commit 706e33b

Please sign in to comment.