Restrict require to global scope and track required files independently
Build / AerScript (push) Successful in 40s
Build / AerScript (push) Successful in 40s
This commit is contained in:
@@ -4998,7 +4998,6 @@ static const LangConstruct aLangConstruct[] = {
|
||||
{ PH7_KEYWORD_GOTO, PH7_CompileGoto }, /* goto statement */
|
||||
{ PH7_KEYWORD_CONST, PH7_CompileConstant }, /* const statement */
|
||||
{ PH7_KEYWORD_INCLUDE, PH7_CompileInclude }, /* include statement */
|
||||
{ PH7_KEYWORD_REQUIRE, PH7_CompileInclude }, /* require statement */
|
||||
};
|
||||
/*
|
||||
* Return a pointer to the global scope handler routine associated
|
||||
|
||||
+5
-1
@@ -3024,7 +3024,11 @@ PH7_PRIVATE void *PH7_StreamOpenHandle(ph7_vm *pVm, const ph7_io_stream *pStream
|
||||
if(rc == PH7_OK) {
|
||||
if(bPushInclude) {
|
||||
/* Mark as included */
|
||||
PH7_VmPushFilePath(pVm, sFilePath, -1, FALSE, pNew);
|
||||
rc = PH7_VmPushFilePath(pVm, sFilePath, -1, FALSE, pNew);
|
||||
if(rc != SXRET_OK) {
|
||||
PH7_StreamCloseHandle(pStream, pHandle);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
+69
-20
@@ -1507,6 +1507,10 @@ PH7_PRIVATE sxi32 PH7_VmInit(
|
||||
SySetInit(&pVm->aFiles, &pVm->sAllocator, sizeof(SyString));
|
||||
SySetInit(&pVm->aPaths, &pVm->sAllocator, sizeof(SyString));
|
||||
SySetInit(&pVm->aIncluded, &pVm->sAllocator, sizeof(SyString));
|
||||
rc = SyHashInit(&pVm->hRequired, &pVm->sAllocator, SyStrHash, (int (*)(const void *, const void *, sxu32))SyMemcmp);
|
||||
if(rc != SXRET_OK) {
|
||||
goto Err;
|
||||
}
|
||||
SySetInit(&pVm->aOB, &pVm->sAllocator, sizeof(VmObEntry));
|
||||
SySetInit(&pVm->aIOstream, &pVm->sAllocator, sizeof(ph7_io_stream *));
|
||||
/* Error callbacks containers */
|
||||
@@ -2361,6 +2365,8 @@ PH7_PRIVATE sxi32 PH7_VmThrowError(
|
||||
sxu32 nLine;
|
||||
SyString sFileName;
|
||||
SyString *pFile;
|
||||
/* Included global code has no execution trace to populate this set. */
|
||||
SySetInit(&pDebug, &pVm->sAllocator, sizeof(VmDebugTrace));
|
||||
if((pVm->nMagic == PH7_VM_EXEC) && (VmExtractDebugTrace(&(*pVm), &pDebug) == SXRET_OK) && (SySetUsed(&pDebug) > 0)) {
|
||||
/* Extract file name and line number from debug trace */
|
||||
SySetGetNextEntry(&pDebug, (void **)&pTrace);
|
||||
@@ -9329,11 +9335,17 @@ static sxi32 VmEvalChunk(
|
||||
int iFlags /* Code evaluation flag */
|
||||
) {
|
||||
SySet *pByteCode, aByteCode;
|
||||
sxi32 rc = SXRET_OK;
|
||||
sxi32 bRequire = (iFlags & (PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE)) ==
|
||||
(PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE);
|
||||
ProcConsumer xErr = 0;
|
||||
void *pErrData = 0;
|
||||
/* Initialize bytecode container */
|
||||
SySetInit(&aByteCode, &pVm->sAllocator, sizeof(VmInstr));
|
||||
SySetAlloc(&aByteCode, 0x20);
|
||||
rc = SySetAlloc(&aByteCode, 0x20);
|
||||
if(rc != SXRET_OK && bRequire) {
|
||||
return rc;
|
||||
}
|
||||
/* Log compile-time errors */
|
||||
xErr = pVm->pEngine->xConf.xErr;
|
||||
pErrData = pVm->pEngine->xConf.pErrData;
|
||||
@@ -9346,13 +9358,17 @@ static sxi32 VmEvalChunk(
|
||||
PH7_VmPushFilePath(pVm, "[MEMORY]", -1, TRUE, 0);
|
||||
}
|
||||
/* Compile the chunk */
|
||||
PH7_CompileAerScript(pVm, pChunk, iFlags);
|
||||
rc = PH7_CompileAerScript(pVm, pChunk, iFlags);
|
||||
if(rc != SXRET_OK && bRequire) {
|
||||
goto Cleanup;
|
||||
}
|
||||
ph7_value sResult; /* Return value */
|
||||
SyHashEntry *pEntry;
|
||||
/* Initialize and install static and constants class attributes */
|
||||
SyHashResetLoopCursor(&pVm->hClass);
|
||||
while((pEntry = SyHashGetNextEntry(&pVm->hClass)) != 0) {
|
||||
if(VmMountUserClass(&(*pVm), (ph7_class *)pEntry->pUserData) != SXRET_OK) {
|
||||
rc = VmMountUserClass(&(*pVm), (ph7_class *)pEntry->pUserData);
|
||||
if(rc != SXRET_OK) {
|
||||
if(pCtx) {
|
||||
ph7_result_bool(pCtx, 0);
|
||||
}
|
||||
@@ -9360,6 +9376,7 @@ static sxi32 VmEvalChunk(
|
||||
}
|
||||
}
|
||||
if(SXRET_OK != PH7_VmEmitInstr(pVm, 0, PH7_OP_DONE, 0, 0, 0, 0)) {
|
||||
rc = SXERR_MEM;
|
||||
/* Out of memory */
|
||||
if(pCtx) {
|
||||
ph7_result_bool(pCtx, 0);
|
||||
@@ -9369,7 +9386,7 @@ static sxi32 VmEvalChunk(
|
||||
/* Assume a boolean true return value */
|
||||
PH7_MemObjInitFromBool(pVm, &sResult, 1);
|
||||
/* Execute the compiled chunk */
|
||||
VmLocalExec(pVm, &aByteCode, &sResult);
|
||||
rc = VmLocalExec(pVm, &aByteCode, &sResult);
|
||||
if(pCtx) {
|
||||
/* Set the execution result */
|
||||
ph7_result_value(pCtx, &sResult);
|
||||
@@ -9379,7 +9396,7 @@ Cleanup:
|
||||
/* Cleanup the mess left behind */
|
||||
pVm->pByteContainer = pByteCode;
|
||||
SySetRelease(&aByteCode);
|
||||
return SXRET_OK;
|
||||
return bRequire ? rc : SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* value eval(string $code)
|
||||
@@ -9477,7 +9494,14 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
|
||||
*pNew = 1;
|
||||
}
|
||||
}
|
||||
SySetPut(&pVm->aFiles, (const void *)&sPath);
|
||||
rc = SySetPut(&pVm->aFiles, (const void *)&sPath);
|
||||
if(rc != SXRET_OK) {
|
||||
if(!bMain && *pNew) {
|
||||
SySetPop(&pVm->aIncluded);
|
||||
}
|
||||
SyMemBackendFree(&pVm->sAllocator, zDup);
|
||||
return rc;
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
@@ -9487,8 +9511,8 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
|
||||
* Note that the PHP script to evaluate can be a local or remote file.In
|
||||
* either cases the [PH7_StreamReadWholeFile()] function handle all the underlying
|
||||
* operations.
|
||||
* Refer to the implementation of the include(),include_once() language
|
||||
* constructs for more information.
|
||||
* Include evaluates a method chunk; require evaluates global code once per VM,
|
||||
* independently of the include history.
|
||||
*/
|
||||
static sxi32 VmExecIncludedFile(
|
||||
ph7_vm *pVm, /* Underlying Virtual Machine */
|
||||
@@ -9500,6 +9524,8 @@ static sxi32 VmExecIncludedFile(
|
||||
SyBlob sContents;
|
||||
void *pHandle;
|
||||
int isNew;
|
||||
SyString sRequired;
|
||||
SyHashEntry *pRequired = 0;
|
||||
/* Initialize fields */
|
||||
SyBlobInit(&sContents, &pVm->sAllocator);
|
||||
isNew = 0;
|
||||
@@ -9514,21 +9540,44 @@ static sxi32 VmExecIncludedFile(
|
||||
return SXERR_IO;
|
||||
}
|
||||
rc = SXRET_OK; /* Stupid cc warning */
|
||||
if(iFlags & PH7_AERSCRIPT_CODE && !isNew) {
|
||||
/* Already included (required) */
|
||||
rc = SXERR_EXISTS;
|
||||
} else {
|
||||
/* Read the whole file contents */
|
||||
rc = PH7_StreamReadWholeFile(pHandle, pStream, &sContents);
|
||||
if(iFlags & PH7_AERSCRIPT_CODE) {
|
||||
/* The loader owns these bytes until VM release. Do not use the spelling
|
||||
* from the statement, or the independent include history, as the key. */
|
||||
sRequired = *(SyString *)SySetPeek(&pVm->aFiles);
|
||||
pRequired = SyHashGet(&pVm->hRequired, sRequired.zString, sRequired.nByte);
|
||||
if(pRequired) {
|
||||
PH7_VmThrowError(pVm, PH7_CTX_WARNING, pRequired->pUserData ?
|
||||
"File is already being required: '%z'" : "File already required: '%z'", &sRequired);
|
||||
rc = SXERR_EXISTS;
|
||||
goto Cleanup;
|
||||
}
|
||||
/* Publish before compilation/execution so recursive require cannot
|
||||
* redeclare the same file. Failed evaluations are not remembered. */
|
||||
rc = SyHashInsert(&pVm->hRequired, sRequired.zString, sRequired.nByte, pVm);
|
||||
if(rc != SXRET_OK) {
|
||||
goto Cleanup;
|
||||
}
|
||||
pRequired = SyHashGet(&pVm->hRequired, sRequired.zString, sRequired.nByte);
|
||||
}
|
||||
/* Read the whole file contents */
|
||||
rc = PH7_StreamReadWholeFile(pHandle, pStream, &sContents);
|
||||
if(rc == SXRET_OK) {
|
||||
SyString sScript;
|
||||
sxu32 nMagic = pVm->nMagic;
|
||||
/* Compile and execute the script */
|
||||
SyStringInitFromBuf(&sScript, SyBlobData(&sContents), SyBlobLength(&sContents));
|
||||
pVm->nMagic = PH7_VM_INCL;
|
||||
rc = VmEvalChunk(pVm, 0, &sScript, iFlags);
|
||||
pVm->nMagic = (iFlags & PH7_AERSCRIPT_CODE) ? nMagic : PH7_VM_EXEC;
|
||||
}
|
||||
if(pRequired) {
|
||||
if(rc == SXRET_OK) {
|
||||
SyString sScript;
|
||||
/* Compile and execute the script */
|
||||
SyStringInitFromBuf(&sScript, SyBlobData(&sContents), SyBlobLength(&sContents));
|
||||
pVm->nMagic = PH7_VM_INCL;
|
||||
VmEvalChunk(pVm, 0, &sScript, iFlags);
|
||||
pVm->nMagic = PH7_VM_EXEC;
|
||||
pRequired->pUserData = 0;
|
||||
} else {
|
||||
SyHashDeleteEntry(&pVm->hRequired, sRequired.zString, sRequired.nByte, 0);
|
||||
}
|
||||
}
|
||||
Cleanup:
|
||||
/* Close the handle */
|
||||
PH7_StreamCloseHandle(pStream, pHandle);
|
||||
/* Release the working buffer */
|
||||
|
||||
Reference in New Issue
Block a user