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 ;
@@ -81,6 +137,20 @@ void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
81137 struct page * * pagep ;
82138 int l ;
83139
140+ if (!is_bnode_offset_valid (node , off ))
141+ return ;
142+
143+ if (len == 0 ) {
144+ pr_err ("requested zero length: "
145+ "NODE: id %u, type %#x, height %u, "
146+ "node_size %u, offset %d, len %d\n" ,
147+ node -> this , node -> type , node -> height ,
148+ node -> tree -> node_size , off , len );
149+ return ;
150+ }
151+
152+ len = check_and_correct_requested_length (node , off , len );
153+
84154 off += node -> page_offset ;
85155 pagep = node -> page + (off >> PAGE_SHIFT );
86156 off &= ~PAGE_MASK ;
@@ -109,6 +179,20 @@ void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
109179 struct page * * pagep ;
110180 int l ;
111181
182+ if (!is_bnode_offset_valid (node , off ))
183+ return ;
184+
185+ if (len == 0 ) {
186+ pr_err ("requested zero length: "
187+ "NODE: id %u, type %#x, height %u, "
188+ "node_size %u, offset %d, len %d\n" ,
189+ node -> this , node -> type , node -> height ,
190+ node -> tree -> node_size , off , len );
191+ return ;
192+ }
193+
194+ len = check_and_correct_requested_length (node , off , len );
195+
112196 off += node -> page_offset ;
113197 pagep = node -> page + (off >> PAGE_SHIFT );
114198 off &= ~PAGE_MASK ;
@@ -133,6 +217,10 @@ void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
133217 hfs_dbg (BNODE_MOD , "copybytes: %u,%u,%u\n" , dst , src , len );
134218 if (!len )
135219 return ;
220+
221+ len = check_and_correct_requested_length (src_node , src , len );
222+ len = check_and_correct_requested_length (dst_node , dst , len );
223+
136224 src += src_node -> page_offset ;
137225 dst += dst_node -> page_offset ;
138226 src_page = src_node -> page + (src >> PAGE_SHIFT );
@@ -187,6 +275,10 @@ void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
187275 hfs_dbg (BNODE_MOD , "movebytes: %u,%u,%u\n" , dst , src , len );
188276 if (!len )
189277 return ;
278+
279+ len = check_and_correct_requested_length (node , src , len );
280+ len = check_and_correct_requested_length (node , dst , len );
281+
190282 src += node -> page_offset ;
191283 dst += node -> page_offset ;
192284 if (dst > src ) {
0 commit comments