Corrected an error in which the "save" command attempts to overwrite

an allocated Tcl argument, and can cause a crash for a filename of
sufficient length.
This commit is contained in:
Tim Edwards 2020-03-19 09:20:50 -04:00
parent f4174d3670
commit 1e4c020b1e
2 changed files with 48 additions and 28 deletions

View File

@ -153,8 +153,11 @@ CmdSave(w, cmd)
DBUpdateStamps();
if (cmd->tx_argc == 2)
{
char *fileName;
if (CmdIllegalChars(cmd->tx_argv[1], "[],", "Cell name"))
return;
cmdSaveCell(locDef, cmd->tx_argv[1], FALSE, TRUE);
}
else cmdSaveCell(locDef, (char *) NULL, FALSE, TRUE);
@ -842,6 +845,8 @@ CmdSelect(w, cmd)
option = SEL_DEFAULT;
else
{
char *fileName;
option = Lookup(optionArgs[0], cmdSelectOption);
if (option < 0 && cmd->tx_argc != 2)
{

View File

@ -33,6 +33,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "database/database.h"
#include "tiles/tile.h"
#include "utils/hash.h"
#include "utils/malloc.h"
#include "windows/windows.h"
#include "dbwind/dbwind.h"
#include "utils/main.h"
@ -589,6 +590,8 @@ cmdSaveCell(cellDef, newName, noninteractive, tryRename)
* place where it was saved.
*/
{
char *fileName = newName;
/* Eliminate the phony labels added for use by rsim */
#ifndef NO_SIM_MODULE
SimEraseLabels();
@ -604,41 +607,41 @@ cmdSaveCell(cellDef, newName, noninteractive, tryRename)
{
if (newName == NULL)
TxPrintf("Must specify name for cell %s.\n", UNNAMED);
newName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (newName == NULL) return;
fileName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (fileName == NULL) return;
}
else if (newName != NULL)
{
newName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (newName == NULL) return;
fileName = cmdCheckNewName(cellDef, newName, TRUE, noninteractive);
if (fileName == NULL) return;
}
else
{
if (cellDef->cd_file == NULL)
{
newName = cmdCheckNewName(cellDef, cellDef->cd_name,
fileName = cmdCheckNewName(cellDef, cellDef->cd_name,
TRUE, noninteractive);
if (newName == NULL) return;
if (fileName == NULL) return;
}
}
DBUpdateStamps();
if (!DBCellWrite(cellDef, newName))
if (!DBCellWrite(cellDef, fileName))
{
TxError("Could not write file. Cell not written.\n");
return;
goto cleanup;
}
if (!tryRename || (newName == NULL) || (strcmp(cellDef->cd_name, newName) == 0))
return;
if (!tryRename || (fileName == NULL) || (strcmp(cellDef->cd_name, fileName) == 0))
goto cleanup;
/* Rename the cell */
if (!DBCellRenameDef(cellDef, newName))
if (!DBCellRenameDef(cellDef, fileName))
{
/* This should never happen */
TxError("Magic error: there is already a cell named \"%s\"\n",
newName);
return;
fileName);
goto cleanup;
}
if (EditCellUse && (cellDef == EditCellUse->cu_def))
@ -660,6 +663,11 @@ cmdSaveCell(cellDef, newName, noninteractive, tryRename)
(void) WindSearch(DBWclientID, (ClientData) NULL, (Rect *) NULL,
cmdSaveWindSet, (ClientData) cellDef);
}
cleanup:
if (fileName != newName)
freeMagic(fileName);
return;
}
/*
@ -694,38 +702,44 @@ cmdCheckNewName(def, newName, tryRename, noninteractive)
bool tryRename;
bool noninteractive;
{
static char newname[256];
static char *yesno[] = { "no", "yes", 0 };
char *filename;
char *prompt;
char *returnname;
int code;
FILE *f;
returnname = newName;
again:
if (newName == NULL)
if (returnname == NULL)
{
if (noninteractive) {
TxError("Can't write file named '%s'\n", def->cd_name);
return NULL;
};
TxPrintf("File for cell %s: [hit return to abort save] ", def->cd_name);
if (TxGetLine(newname, sizeof newname) == NULL || newname[0] == '\0')
returnname = (char *)mallocMagic(1024 * sizeof(char));
if (TxGetLine(returnname, sizeof returnname) == NULL || returnname[0] == '\0')
{
TxPrintf("Cell not saved.\n");
freeMagic(returnname);
return ((char *) NULL);
}
if (CmdIllegalChars(newname, "[],", "Cell name"))
if (CmdIllegalChars(returnname, "[],", "Cell name"))
{
freeMagic(returnname);
goto again;
newName = newname;
}
}
/* Remove any ".mag" file extension from the name */
else if (!strcmp(newName + strlen(newName) - 4, ".mag"))
*(newName + strlen(newName) - 4) = '\0';
if (!strcmp(returnname + strlen(returnname) - 4, ".mag"))
*(returnname + strlen(returnname) - 4) = '\0';
if (strcmp(newName, def->cd_name) != 0)
if (strcmp(returnname, def->cd_name) != 0)
{
if (f = PaOpen(newName, "r", DBSuffix, ".", (char *) NULL, &filename))
if (f = PaOpen(returnname, "r", DBSuffix, ".", (char *) NULL, &filename))
{
(void) fclose(f);
if (noninteractive) {
@ -740,23 +754,24 @@ again:
if (code == 0)
{
/* No -- don't overwrite */
newName = NULL;
if (returnname != newName) freeMagic(returnname);
returnname = NULL;
goto again;
}
}
}
if (tryRename && DBCellLookDef(newName) != NULL)
if (tryRename && DBCellLookDef(returnname) != NULL)
{
TxError("Can't rename cell '%s' to '%s' because that cell already exists.\n",
def->cd_name, newName);
def->cd_name, returnname);
if (returnname != newName) freeMagic(returnname);
if (noninteractive) return NULL;
newName = NULL;
returnname = NULL;
goto again;
}
}
return (newName);
return (returnname);
}
/*