1818#include "hfsplus_fs.h"
1919#include "hfsplus_raw.h"
2020
21+ static inline
22+ bool is_bnode_offset_valid (struct hfs_bnode * node , int off )
23+ {
24+ bool is_valid = off < node -> tree -> node_size ;
25+
26+ if (!is_valid ) {
27+ pr_err ("requested invalid offset: "
28+ "NODE: id %u, type %#x, height %u, "
29+ "node_size %u, offset %d\n" ,
30+ node -> this , node -> type , node -> height ,
31+ node -> tree -> node_size , off );
32+ }
33+
34+ return is_valid ;
35+ }
36+
37+ static inline
38+ int check_and_correct_requested_length (struct hfs_bnode * node , int off , int len )
39+ {
40+ unsigned int node_size ;
41+
42+ if (!is_bnode_offset_valid (node , off ))
43+ return 0 ;
44+
45+ node_size = node -> tree -> node_size ;
46+
47+ if ((off + len ) > node_size ) {
48+ int new_len = (int )node_size - off ;
49+
50+ pr_err ("requested length has been corrected: "
51+ "NODE: id %u, type %#x, height %u, "
52+ "node_size %u, offset %d, "
53+ "requested_len %d, corrected_len %d\n" ,
54+ node -> this , node -> type , node -> height ,
55+ node -> tree -> node_size , off , len , new_len );
56+
57+ return new_len ;
58+ }
59+
60+ return len ;
61+ }
62+
2163/* Copy a specified range of bytes from the raw data of a node */
2264void hfs_bnode_read (struct hfs_bnode * node , void * buf , int off , int len )
2365{
2466 struct page * * pagep ;
2567 int l ;
2668
69+ if (!is_bnode_offset_valid (node , off ))
70+ return ;
71+
72+ if (len == 0 ) {
73+ pr_err ("requested zero length: "
74+ "NODE: id %u, type %#x, height %u, "
75+ "node_size %u, offset %d, len %d\n" ,
76+ node -> this , node -> type , node -> height ,
77+ node -> tree -> node_size , off , len );
78+ return ;
79+ }
80+
81+ len = check_and_correct_requested_length (node , off , len );
82+
2783 off += node -> page_offset ;
2884 pagep = node -> page + (off >> PAGE_SHIFT );
2985 off &= ~PAGE_MASK ;
@@ -83,6 +139,20 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
83139 struct page * * pagep ;
84140 int l ;
85141
142+ if (!is_bnode_offset_valid (node , off ))
143+ return ;
144+
145+ if (len == 0 ) {
146+ pr_err ("requested zero length: "
147+ "NODE: id %u, type %#x, height %u, "
148+ "node_size %u, offset %d, len %d\n" ,
149+ node -> this , node -> type , node -> height ,
150+ node -> tree -> node_size , off , len );
151+ return ;
152+ }
153+
154+ len = check_and_correct_requested_length (node , off , len );
155+
86156 off += node -> page_offset ;
87157 pagep = node -> page + (off >> PAGE_SHIFT );
88158 off &= ~PAGE_MASK ;
@@ -113,6 +183,20 @@ void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
113183 struct page * * pagep ;
114184 int l ;
115185
186+ if (!is_bnode_offset_valid (node , off ))
187+ return ;
188+
189+ if (len == 0 ) {
190+ pr_err ("requested zero length: "
191+ "NODE: id %u, type %#x, height %u, "
192+ "node_size %u, offset %d, len %d\n" ,
193+ node -> this , node -> type , node -> height ,
194+ node -> tree -> node_size , off , len );
195+ return ;
196+ }
197+
198+ len = check_and_correct_requested_length (node , off , len );
199+
116200 off += node -> page_offset ;
117201 pagep = node -> page + (off >> PAGE_SHIFT );
118202 off &= ~PAGE_MASK ;
@@ -139,6 +223,10 @@ void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
139223 hfs_dbg (BNODE_MOD , "copybytes: %u,%u,%u\n" , dst , src , len );
140224 if (!len )
141225 return ;
226+
227+ len = check_and_correct_requested_length (src_node , src , len );
228+ len = check_and_correct_requested_length (dst_node , dst , len );
229+
142230 src += src_node -> page_offset ;
143231 dst += dst_node -> page_offset ;
144232 src_page = src_node -> page + (src >> PAGE_SHIFT );
@@ -196,6 +284,10 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
196284 hfs_dbg (BNODE_MOD , "movebytes: %u,%u,%u\n" , dst , src , len );
197285 if (!len )
198286 return ;
287+
288+ len = check_and_correct_requested_length (node , src , len );
289+ len = check_and_correct_requested_length (node , dst , len );
290+
199291 src += node -> page_offset ;
200292 dst += node -> page_offset ;
201293 if (dst > src ) {
0 commit comments