@@ -99,6 +99,10 @@ module json_value_module
99
99
! "value": 0.1E+1
100
100
! }
101
101
! ````
102
+ !
103
+ ! @warning Pointers of this type should only be allocated
104
+ ! using the methods from [[json_core(type)]].
105
+
102
106
type,public :: json_value
103
107
104
108
! force the constituents to be stored contiguously
@@ -2027,6 +2031,17 @@ end subroutine json_value_create
2027
2031
! @note The original FSON version of this
2028
2032
! routine was not properly freeing the memory.
2029
2033
! It was rewritten.
2034
+ !
2035
+ ! @note This routine destroys this variable, it's children, and
2036
+ ! (if `destroy_next` is true) the subsequent elements in
2037
+ ! an object or array. It does not destroy the parent or
2038
+ ! previous elements.
2039
+ !
2040
+ ! @Note There is some protection here to enable destruction of
2041
+ ! improperly-created linked lists. However, likely there
2042
+ ! are cases not handled. Use the [[json_value_validate]]
2043
+ ! method to validate a JSON structure that was manually
2044
+ ! created using [[json_value]] pointers.
2030
2045
2031
2046
recursive subroutine json_value_destroy (json ,p ,destroy_next )
2032
2047
@@ -2037,8 +2052,9 @@ recursive subroutine json_value_destroy(json,p,destroy_next)
2037
2052
logical (LK),intent (in ),optional :: destroy_next ! ! if true, then `p%next`
2038
2053
! ! is also destroyed (default is true)
2039
2054
2040
- logical (LK) :: des_next
2041
- type (json_value), pointer :: child
2055
+ logical (LK) :: des_next ! ! local copy of `destroy_next` optional argument
2056
+ type (json_value), pointer :: child ! ! for getting child elements
2057
+ logical :: circular ! ! to check to malformed linked lists
2042
2058
2043
2059
if (associated (p)) then
2044
2060
@@ -2052,16 +2068,26 @@ recursive subroutine json_value_destroy(json,p,destroy_next)
2052
2068
2053
2069
call destroy_json_data(p)
2054
2070
2071
+ if (associated (p% next)) then
2072
+ ! check for circular references:
2073
+ if (associated (p, p% next)) nullify(p% next)
2074
+ end if
2075
+
2055
2076
if (associated (p% children)) then
2056
2077
do while (p% n_children > 0 )
2057
2078
child = > p% children
2058
2079
if (associated (child)) then
2059
2080
p% children = > p% children% next
2060
2081
p% n_children = p% n_children - 1
2061
- call json% destroy(child,.false. )
2082
+ ! check children for circular references:
2083
+ circular = (associated (p% children) .and. &
2084
+ associated (p% children,child))
2085
+ call json% destroy(child,destroy_next= .false. )
2086
+ if (circular) exit
2062
2087
else
2063
- call json% throw_exception(' Error in json_value_destroy: ' // &
2064
- ' Malformed JSON linked list' )
2088
+ ! it is a malformed JSON object. But, we will
2089
+ ! press ahead with the destroy process, since
2090
+ ! otherwise, there would be no way to destroy it.
2065
2091
exit
2066
2092
end if
2067
2093
end do
@@ -2075,7 +2101,7 @@ recursive subroutine json_value_destroy(json,p,destroy_next)
2075
2101
if (associated (p% parent)) nullify(p% parent)
2076
2102
if (associated (p% tail)) nullify(p% tail)
2077
2103
2078
- deallocate (p)
2104
+ if ( associated (p)) deallocate (p)
2079
2105
nullify(p)
2080
2106
2081
2107
end if
@@ -2657,9 +2683,15 @@ recursive subroutine check_if_valid(p,require_parent)
2657
2683
2658
2684
! now, check next one:
2659
2685
if (associated (p% next)) then
2660
- ! if it's an element in an
2661
- ! array, then require a parent:
2662
- call check_if_valid(p% next,require_parent= .true. )
2686
+ if (associated (p,p% next)) then
2687
+ error_msg = ' circular linked list'
2688
+ is_valid = .false.
2689
+ return
2690
+ else
2691
+ ! if it's an element in an
2692
+ ! array, then require a parent:
2693
+ call check_if_valid(p% next,require_parent= .true. )
2694
+ end if
2663
2695
end if
2664
2696
2665
2697
if (associated (p% children)) then
0 commit comments