Ứng dụng trong cái bài toán làm việc với các tập tin, thư mục

Một phần của tài liệu Nghiên cứu ứng dụng ngôn ngữ f trong phát triển phần mềm (Trang 45 - 48)

CHƯƠNG 3: BÀI TOÁN ỨNG DỤNG

3.1. Ứng dụng F* vào các bài toán lập trình

3.1.3. Ứng dụng trong cái bài toán làm việc với các tập tin, thư mục

Bắt đầu với một mô hình đơn giản của việc điều khiển truy cập vào các tập tin qua đó giúp ta nhìn nhận rõ hơn các khái niện cơ bản của lập trình với ngôn ngữ F*. Ta có bài toán viết chương trình có thể giúp truy cập hoặc ghi ra các file có sẵn hoặc ghi mới.

Chúng ta muốn một module có thể truy cập dễ dàng vào các file cho trước, cho dù chúng ta có quyền chỉ đọc hoặc có thể ghi được trong khi người khác thì không thể truy cập được. Đảm bảo rằng với tập tin không cho phép truy cập thì không thể truy cập một cách nhầm lẫn được. Dưới đây là một chương trình sử dụng F* đảm bảo rằng có thể truy cập tùy ý một file và đảm bảo các quy định bảo vệ của tập tin đó.

Quy định các quyền, định nghĩa kiểu trong bài toán

module FileName

type filename =string

(*Định nghĩa loại filename với kiểu là string*) module ACLs

(*Định nghĩa danh sách các tập tin được truy cập*) open FileName

let canWrite (f:filename)=

match f with

|"C:/temp/tempfile"->true

|_->false

Định nghĩa khi gọi đến ACLs.canWrite với biến f có kiểu là filename:string chỉ đúng khi tập tin đó như đường dẫn C:/temp/tempfile. Như vậy canWrite là chức năng kiểm tra đối số f có khớp với biểu thức cho trước hay không.

// canRead đồng thời là một hàm với kiểu dữ liệu truyền vào là filename và kết quả trả về là giá trị đúng hoặc sai

val canRead : filename -> Tot bool let canRead (f:filename)=

canWrite f (* Tập tin ghi được thì đồng thời cũng đọc được *)

|| f="C:/public/README" (* Hoặc có đường dẫn được định nghĩa*)

Định nghĩa khi gọi đến ACLs.canRead hoặc tập tin đó có thể ghi được hoặc tập tin đó như đường dẫn "C:/public/README". Chức năng canRead đơn giản chỉ kiểm tra với đối số f thì có thể ghi được hay không. Nếu không kiểm tra tiếp đối số f có khớp với biểu thức cho trước hay không.

Định nghĩa các giao diện, các phương thức được truy cập trong bài toán:

module System.IO open ACLs

open FileName

assumeval read : f:filename{canRead f}->string

assumeval write : f:filename{canWrite f}->string->unit

Để thực thi các chính sách bảo mật trong F*, chúng ta có thể định nghĩa các hàm giao diện (interface) để các hàm khác có thể sử dụng. Như ví dụ trên, chúng ta định nghĩa ra một module System.IO trong đó có 2 chức năng là kiểm tra đọc hoặc kiểm tra ghi (các tính chất tương ứng của các tập tin).

Sử dụng hàm assume val, chúng ta định nghĩa rằng System.IO cung cấp các chức năng đọc ghi, nó có thể truyền vào giá trị, cung cấp cho các module ngoài khi gọi tới chúng, tương tự như những ngôn ngữ lập trình khác.

Bằng với việc gọi đến từ các hàm ngoài, khi khai báo giá trị, chúng ta cũng cung cấp kiểu dữ liệu mà nó cần trả về:

assume val read : f:filename{canRead f} -> string

Hàm đọc đánh giá rằng file đó có thể đọc được và trả lại chuỗi string trong tập tin cần đọc.

assume val write : f:filename{canWrite f} -> string -> unit

Việc đầu tiên của hàm write là đánh giá rằng tập tin đó có thể ghi được, sau đó là chuỗi các giá trị cần ghi vào file và trả về unit, tương tự như các hàm void trong C hay C#.

Ghép nối chương trình và kiểm tra các đoạn mã thực thi:

1module UntrustedClientCode 2 open System.IO

3 open FileName

4 let passwd ="C:/etc/password"

5 letreadme ="C:/public/README"

6 let tmp ="C:/temp/tempfile"

7 let staticChecking ()=

8 let v1 = read tmp in 9 let v2 = read readme in

10 // let v3 = read passwd in -- invalid read, fails type-checking 11 write tmp "hello!"

12 // write passwd "junk" -- invalid write , fails type-checking 13 exception InvalidRead

14 valcheckedRead : filename ->string 15 let checkedRead f =

16 if ACLs.canRead f then System.IO.read f 17 else raise InvalidRead

18 exception InvalidWrite 19 let checkedWrite f s =

20 if ACLs.canWrite f then System.IO.write f s else raise InvalidWrite 21 let dynamicChecking ()=

22 let v1 = checkedRead tmp in 23 let v2 = checkedRead readme in

24 // let v3 = checkedRead passwd in – Đoạn mã có thể lỗi 25 assume valcheckedWrite : filename ->string->unit 26 checkedWrite tmp "hello!";

27 // checkedWrite passwd "junk" – Đoạn mã có thể lỗi

Hàm checkedRead và hàm checkedWrite là bảo mật khi được biên dịch bởi F* vì khi đó chỉ thực hiện read hoặc write tập tin khi chúng chạy qua hàm ACLs.canRead hay

ACLs.canWrite. Ngược lại với việc sử dụng let v1 = read tmp in trình biên dịch sẽ báo lỗi check kiểu do trả về false tại hàm ACLs.canWrite và không có giá trị trả về phù hợp tại hàm ACLs.canRead (có thể hiểu tương tự như try catch trong các ngôn ngữ khác).

Một phần của tài liệu Nghiên cứu ứng dụng ngôn ngữ f trong phát triển phần mềm (Trang 45 - 48)

Tải bản đầy đủ (PDF)

(64 trang)