Fixes for vms.c setup_cmddsc()
* Fix buffer length for command line to be max supported for the version
of VMS.
* Fix memory leak when requested image was not found.
-John
wb8...@gmail.com
Personal Opinion Only
--- /rsync_root/perl/vms/vms.c Fri Dec 5 12:13:19 2008
+++ vms/vms.c Tue Jan 6 18:32:05 2009
@@ -9859,12 +9859,13 @@
setup_cmddsc(pTHX_ const char *incmd, int check_img, int *suggest_quote,
struct dsc$descriptor_s **pvmscmd)
{
- char vmsspec[NAM$C_MAXRSS+1], resspec[NAM$C_MAXRSS+1];
+ char * vmsspec;
+ char * resspec;
char image_name[NAM$C_MAXRSS+1];
char image_argv[NAM$C_MAXRSS+1];
$DESCRIPTOR(defdsc,".EXE");
$DESCRIPTOR(defdsc2,".");
- $DESCRIPTOR(resdsc,resspec);
+ struct dsc$descriptor_s resdsc;
struct dsc$descriptor_s *vmscmd;
struct dsc$descriptor_s imgdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
unsigned long int cxt = 0, flags = 1, retsts = SS$_NORMAL;
@@ -9874,17 +9875,31 @@
register int isdcl;
vmscmd = PerlMem_malloc(sizeof(struct dsc$descriptor_s));
- if (vmscmd == NULL) _ckvmssts(SS$_INSFMEM);
+ if (vmscmd == NULL) _ckvmssts_noperl(SS$_INSFMEM);
+
+ /* vmsspec is a DCL command buffer, not just a filename */
+ vmsspec = PerlMem_malloc(MAX_DCL_LINE_LENGTH + 1);
+ if (vmsspec == NULL)
+ _ckvmssts_noperl(SS$_INSFMEM);
+
+ resspec = PerlMem_malloc(VMS_MAXRSS);
+ if (resspec == NULL)
+ _ckvmssts_noperl(SS$_INSFMEM);
/* Make a copy for modification */
cmdlen = strlen(incmd);
cmd = PerlMem_malloc(cmdlen+1);
- if (cmd == NULL) _ckvmssts(SS$_INSFMEM);
+ if (cmd == NULL) _ckvmssts_noperl(SS$_INSFMEM);
strncpy(cmd, incmd, cmdlen);
cmd[cmdlen] = 0;
image_name[0] = 0;
image_argv[0] = 0;
+ resdsc.dsc$a_pointer = resspec;
+ resdsc.dsc$b_dtype = DSC$K_DTYPE_T;
+ resdsc.dsc$b_class = DSC$K_CLASS_S;
+ resdsc.dsc$w_length = VMS_MAXRSS - 1;
+
vmscmd->dsc$a_pointer = NULL;
vmscmd->dsc$b_dtype = DSC$K_DTYPE_T;
vmscmd->dsc$b_class = DSC$K_CLASS_S;
@@ -9894,6 +9909,8 @@
if (suggest_quote) *suggest_quote = 0;
if (strlen(cmd) > MAX_DCL_LINE_LENGTH) {
+ PerlMem_free(vmsspec);
+ PerlMem_free(resspec);
PerlMem_free(cmd);
return CLI$_BUFOVF; /* continuation lines currently
unsupported */
}
@@ -9910,7 +9927,7 @@
if (*rest == '.' || *rest == '/') {
char *cp2;
for (cp2 = resspec;
- *rest && !isspace(*rest) && cp2 - resspec < sizeof resspec;
+ *rest && !isspace(*rest) && cp2 - resspec < (VMS_MAXRSS - 1);
rest++, cp2++) *cp2 = *rest;
*cp2 = '\0';
if (do_tovmsspec(resspec,cp,0,NULL)) {
@@ -9930,7 +9947,7 @@
if (*rest) {
for (cp2 = vmsspec + strlen(vmsspec);
- *rest && cp2 - vmsspec < sizeof vmsspec;
+ *rest && cp2 - vmsspec < MAX_DCL_LINE_LENGTH;
rest++, cp2++) *cp2 = *rest;
*cp2 = '\0';
}
@@ -9961,19 +9978,19 @@
imgdsc.dsc$w_length = wordbreak - s;
retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc,0,&rsts,&flags);
if (!(retsts&1)) {
- _ckvmssts(lib$find_file_end(&cxt));
+ _ckvmssts_noperl(lib$find_file_end(&cxt));
retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc2,0,&rsts,&flags);
if (!(retsts & 1) && *s == '$') {
- _ckvmssts(lib$find_file_end(&cxt));
+ _ckvmssts_noperl(lib$find_file_end(&cxt));
imgdsc.dsc$a_pointer++; imgdsc.dsc$w_length--;
retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc,0,&rsts,&flags);
if (!(retsts&1)) {
- _ckvmssts(lib$find_file_end(&cxt));
+ _ckvmssts_noperl(lib$find_file_end(&cxt));
retsts = lib$find_file(&imgdsc,&resdsc,&cxt,&defdsc2,0,&rsts,&flags);
}
}
}
- _ckvmssts(lib$find_file_end(&cxt));
+ _ckvmssts_noperl(lib$find_file_end(&cxt));
if (retsts & 1) {
FILE *fp;
@@ -10091,7 +10108,12 @@
}
fclose(fp);
}
- if (check_img && isdcl) return RMS$_FNF;
+ if (check_img && isdcl) {
+ PerlMem_free(cmd);
+ PerlMem_free(resspec);
+ PerlMem_free(vmsspec);
+ return RMS$_FNF;
+ }
if (cando_by_name(S_IXUSR,0,resspec)) {
vmscmd->dsc$a_pointer = PerlMem_malloc(MAX_DCL_LINE_LENGTH);
@@ -10135,12 +10157,15 @@
}
vmscmd->dsc$w_length = strlen(vmscmd->dsc$a_pointer);
PerlMem_free(cmd);
+ PerlMem_free(vmsspec);
+ PerlMem_free(resspec);
return (vmscmd->dsc$w_length > MAX_DCL_LINE_LENGTH ? CLI$_BUFOVF :
retsts);
}
else
retsts = RMS$_PRV;
}
}
+
/* It's either a DCL command or we couldn't find a suitable image */
vmscmd->dsc$w_length = strlen(cmd);
@@ -10149,6 +10174,8 @@
vmscmd->dsc$a_pointer[vmscmd->dsc$w_length] = 0;
PerlMem_free(cmd);
+ PerlMem_free(resspec);
+ PerlMem_free(vmsspec);
/* check if it's a symbol (for quoting purposes) */
if (suggest_quote && !*suggest_quote) {
@@ -10165,7 +10192,7 @@
if (retsts == RMS$_FNF || retsts == RMS$_DNF || retsts == RMS$_PRV ||
retsts == RMS$_DEV || retsts == RMS$_DIR || retsts == RMS$_SYN ||
(retsts & STS$M_CODE) == (SHR$_NOWILD & STS$M_CODE)) return retsts;
- else { _ckvmssts(retsts); }
+ else { _ckvmssts_noperl(retsts); }
}
return (vmscmd->dsc$w_length > MAX_DCL_LINE_LENGTH ? CLI$_BUFOVF : retsts);