mirror of
https://github.com/usetrmnl/byos_laravel.git
synced 2026-01-14 07:27:47 +00:00
fix: check arg length (external liquid renderer)
This commit is contained in:
parent
c61acf10ce
commit
b9fd81299d
2 changed files with 62 additions and 3 deletions
|
|
@ -11,6 +11,7 @@ use App\Liquid\Filters\StandardFilters;
|
||||||
use App\Liquid\Filters\StringMarkup;
|
use App\Liquid\Filters\StringMarkup;
|
||||||
use App\Liquid\Filters\Uniqueness;
|
use App\Liquid\Filters\Uniqueness;
|
||||||
use App\Liquid\Tags\TemplateTag;
|
use App\Liquid\Tags\TemplateTag;
|
||||||
|
use App\Services\PluginImportService;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
@ -372,14 +373,14 @@ class Plugin extends Model
|
||||||
* @param array $context The render context data
|
* @param array $context The render context data
|
||||||
* @return string The rendered HTML
|
* @return string The rendered HTML
|
||||||
*
|
*
|
||||||
* @throws LiquidException
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function renderWithExternalLiquidRenderer(string $template, array $context): string
|
private function renderWithExternalLiquidRenderer(string $template, array $context): string
|
||||||
{
|
{
|
||||||
$liquidPath = config('services.trmnl.liquid_path');
|
$liquidPath = config('services.trmnl.liquid_path');
|
||||||
|
|
||||||
if (empty($liquidPath)) {
|
if (empty($liquidPath)) {
|
||||||
throw new LiquidException('External liquid renderer path is not configured');
|
throw new Exception('External liquid renderer path is not configured');
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTML encode the template
|
// HTML encode the template
|
||||||
|
|
@ -389,9 +390,12 @@ class Plugin extends Model
|
||||||
$jsonContext = json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
$jsonContext = json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||||
|
|
||||||
if ($jsonContext === false) {
|
if ($jsonContext === false) {
|
||||||
throw new LiquidException('Failed to encode render context as JSON: '.json_last_error_msg());
|
throw new Exception('Failed to encode render context as JSON: '.json_last_error_msg());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate argument sizes
|
||||||
|
app(PluginImportService::class)->validateExternalRendererArguments($encodedTemplate, $jsonContext, $liquidPath);
|
||||||
|
|
||||||
// Execute the external renderer
|
// Execute the external renderer
|
||||||
$process = Process::run([
|
$process = Process::run([
|
||||||
$liquidPath,
|
$liquidPath,
|
||||||
|
|
|
||||||
|
|
@ -381,4 +381,59 @@ class PluginImportService
|
||||||
'sharedLiquidPath' => $sharedLiquidPath,
|
'sharedLiquidPath' => $sharedLiquidPath,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that template and context are within command-line argument limits
|
||||||
|
*
|
||||||
|
* @param string $template The liquid template string
|
||||||
|
* @param string $jsonContext The JSON-encoded context
|
||||||
|
* @param string $liquidPath The path to the liquid renderer executable
|
||||||
|
* @return void
|
||||||
|
*
|
||||||
|
* @throws Exception If the template or context exceeds argument limits
|
||||||
|
*/
|
||||||
|
public function validateExternalRendererArguments(string $template, string $jsonContext, string $liquidPath): void
|
||||||
|
{
|
||||||
|
// MAX_ARG_STRLEN on Linux is typically 131072 (128KB) for individual arguments
|
||||||
|
// ARG_MAX is the total size of all arguments (typically 2MB on modern systems)
|
||||||
|
$maxIndividualArgLength = 131072; // 128KB - MAX_ARG_STRLEN limit
|
||||||
|
$maxTotalArgLength = $this->getMaxArgumentLength();
|
||||||
|
|
||||||
|
// Check individual argument sizes (template and context are the largest)
|
||||||
|
if (strlen($template) > $maxIndividualArgLength || strlen($jsonContext) > $maxIndividualArgLength) {
|
||||||
|
throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate total size of all arguments (path + flags + template + context)
|
||||||
|
// Add overhead for path, flags, and separators (conservative estimate: ~200 bytes)
|
||||||
|
$totalArgSize = strlen($liquidPath) + strlen('--template') + strlen($template)
|
||||||
|
+ strlen('--context') + strlen($jsonContext) + 200;
|
||||||
|
|
||||||
|
if ($totalArgSize > $maxTotalArgLength) {
|
||||||
|
throw new Exception('Context too large for external liquid renderer. Reduce the size of the Payload or Template.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum argument length for command-line arguments
|
||||||
|
*
|
||||||
|
* @return int Maximum argument length in bytes
|
||||||
|
*/
|
||||||
|
private function getMaxArgumentLength(): int
|
||||||
|
{
|
||||||
|
// Try to get ARG_MAX from system using getconf
|
||||||
|
$argMax = null;
|
||||||
|
if (function_exists('shell_exec')) {
|
||||||
|
$result = @shell_exec('getconf ARG_MAX 2>/dev/null');
|
||||||
|
if ($result !== null && is_numeric(trim($result))) {
|
||||||
|
$argMax = (int) trim($result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use conservative fallback if ARG_MAX cannot be determined
|
||||||
|
// ARG_MAX on macOS is typically 262144 (256KB), on Linux it's usually 2097152 (2MB)
|
||||||
|
// We use 200KB as a conservative limit that works on both systems
|
||||||
|
// Note: ARG_MAX includes environment variables, so we leave headroom
|
||||||
|
return $argMax !== null ? min($argMax, 204800) : 204800;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue