@@ -99,6 +99,10 @@ module json_value_module
9999 ! "value": 0.1E+1
100100 ! }
101101 ! ````
102+ !
103+ ! @warning Pointers of this type should only be allocated
104+ ! using the methods from [[json_core(type)]].
105+
102106 type,public :: json_value
103107
104108 ! force the constituents to be stored contiguously
@@ -2027,6 +2031,17 @@ end subroutine json_value_create
20272031! @note The original FSON version of this
20282032! routine was not properly freeing the memory.
20292033! 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.
20302045
20312046 recursive subroutine json_value_destroy (json ,p ,destroy_next )
20322047
@@ -2037,8 +2052,9 @@ recursive subroutine json_value_destroy(json,p,destroy_next)
20372052 logical (LK),intent (in ),optional :: destroy_next ! ! if true, then `p%next`
20382053 ! ! is also destroyed (default is true)
20392054
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
20422058
20432059 if (associated (p)) then
20442060
@@ -2052,16 +2068,26 @@ recursive subroutine json_value_destroy(json,p,destroy_next)
20522068
20532069 call destroy_json_data(p)
20542070
2071+ if (associated (p% next)) then
2072+ ! check for circular references:
2073+ if (associated (p, p% next)) nullify(p% next)
2074+ end if
2075+
20552076 if (associated (p% children)) then
20562077 do while (p% n_children > 0 )
20572078 child = > p% children
20582079 if (associated (child)) then
20592080 p% children = > p% children% next
20602081 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
20622087 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.
20652091 exit
20662092 end if
20672093 end do
@@ -2075,7 +2101,7 @@ recursive subroutine json_value_destroy(json,p,destroy_next)
20752101 if (associated (p% parent)) nullify(p% parent)
20762102 if (associated (p% tail)) nullify(p% tail)
20772103
2078- deallocate (p)
2104+ if ( associated (p)) deallocate (p)
20792105 nullify(p)
20802106
20812107 end if
@@ -2657,9 +2683,15 @@ recursive subroutine check_if_valid(p,require_parent)
26572683
26582684 ! now, check next one:
26592685 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
26632695 end if
26642696
26652697 if (associated (p% children)) then
0 commit comments