Tài liệu
/
Làm rối VM
/

Hành vi của direct eval

Direct eval() vô hiệu hóa làm rối VM

Nếu một hàm chứa lệnh gọi direct eval(code) ở bất kỳ đâu trong thân của nó (kể cả trong các hàm lồng nhau), thì hàm đó sẽ bị làm rối VM bỏ qua và trình làm rối báo một cảnh báo VMDynamicCodeSkipped (nêu tên hàm khi hàm có tên). Ở chế độ root (mặc định), toàn bộ hàm đó cùng mọi hàm lồng bên trong đều bị bỏ qua; ở chế độ comment, một hàm lồng nhau mà bạn đánh dấu riêng vẫn được ảo hóa, trừ khi chính nó chứa eval. Một direct eval có đối số không tĩnh còn phát ra cảnh báo DynamicCodeRenameRisk. Lý do là direct eval có quyền truy cập các biến cục bộ của hàm bao quanh, trong khi các biến này không còn khả dụng khi hàm được biên dịch thành bytecode VM.

Quan trọng với mã được bọc trong IIFE. Nếu một IIFE cấp cao nhất chứa bất kỳ direct eval nào ở sâu bên trong, toàn bộ IIFE (bao gồm tất cả mã của bạn) sẽ không được làm rối VM.

JavaScript

Việc gỡ bọc IIFE có một đánh đổi: khi các hàm của bạn nằm ở cấp cao nhất, chỉ hàm vi phạm bị bỏ qua, nhưng các hàm còn lại giờ là hàm cấp gốc, nên làm rối VM giữ nguyên tên của chúng. Xem Ẩn tên hàm khỏi phân tích của LLM để biết cách giữ những tên đó ngoài đầu ra.

Các dạng gián tiếp như (0, eval)(code) và window.eval(code) không chặn làm rối VM. eval?.(code) là một ngoại lệ: JavaScript chạy nó như eval gián tiếp, nhưng trình làm rối thận trọng xử lý nó như direct eval và bỏ qua hàm đó.

Hàm khởi tạo Function (new Function(body) / Function(body)) được xử lý theo cùng cách khi đối số thân hàm là động. Một hàm chứa lệnh gọi new Function(...) động cũng bị bỏ qua, kèm cảnh báo VMDynamicCodeSkipped. Giống như với một direct eval động, trình làm rối thêm cảnh báo DynamicCodeRenameRisk, vì thân hàm được dựng lúc chạy có thể tham chiếu tới các định danh đã bị đổi tên. Các lệnh gọi hoàn toàn tĩnh như new Function('a', 'b', 'return a + b') thì không bị bỏ qua.

Eval gián tiếp và hàm khởi tạo Function thực thi trong phạm vi toàn cục. Chúng không thể đọc các biến cục bộ của nơi gọi, nhưng vẫn có thể lỗi nếu tham chiếu tới các biến toàn cục đã bị đổi tên hoặc bị loại bỏ. Một thân hàm tĩnh chỉ dùng các tham số của chính nó, như new Function('a', 'b', 'return a + b'), tránh được sự phụ thuộc đó. Hãy xem lại các cảnh báo và kiểm thử bundle cuối cùng; chỉ đổi cú pháp eval không làm cho mã động tùy ý trở nên an toàn.

Lối thoát (v6.14.0+): đặt vmForceCompileDynamicCode: true (hoặc bật công tắc Force Compile Dynamic Code trong nhóm Ghi đè của phần VM) để vẫn chuyển hàm bao quanh thành bytecode và ẩn cảnh báo VMDynamicCodeSkipped. Nó không thể sửa vấn đề phạm vi: bên trong một hàm được buộc biên dịch, eval trực tiếp không thể đọc hay ghi các biến cục bộ của hàm, các tham số của hàm, hay các biến của một hàm bao ngoài đã được ảo hóa, ngay cả khi mã là một chuỗi ký tự cố định. Chỉ dùng nó khi mã được eval không tham chiếu tới gì ngoài các biến toàn cục. DynamicCodeRenameRisk vẫn tiếp tục được phát ra khi bật tùy chọn này, vì rủi ro đổi tên mà nó mô tả độc lập với việc VM bỏ qua hàm.

Xem Làm rối VM với eval và new Function để có bảng đầy đủ, dạng của các cảnh báo và các cách khắc phục.