Browse Source

initial package creation

Signed-off-by: Toshaan Bharvani <toshaan@powerel.org>
master
Toshaan Bharvani 5 months ago
parent
commit
668430b36d
  1. 25
      SOURCES/0001-iterration-problem-for-non-decimal-string.patch
  2. 851
      SOURCES/0002-add-mantest.patch
  3. 244
      SOURCES/0003-fix-pthread-segfault.patch
  4. 4562
      SOURCES/0004-make-jq-fast.patch
  5. 27596
      SOURCES/jq-decimal-literal-number.patch
  6. 124
      SPECS/jq.spec

25
SOURCES/0001-iterration-problem-for-non-decimal-string.patch

@ -0,0 +1,25 @@
diff -up jq-1.6/src/jv.c.iteration jq-1.6/src/jv.c
--- jq-1.6/src/jv.c.iteration 2022-10-21 14:17:26.977551386 +0200
+++ jq-1.6/src/jv.c 2022-10-21 14:18:43.562430867 +0200
@@ -308,6 +308,7 @@ static jv jvp_literal_number_new(const c
n->refcnt = JV_REFCNT_INIT;
n->literal_data = NULL;
decContext *ctx = DEC_CONTEXT();
+ decContextClearStatus(ctx, DEC_Conversion_syntax);
decNumberFromString(&n->num_decimal, literal, ctx);
n->num_double = NAN;
diff -up jq-1.6/tests/optional.test.iteration jq-1.6/tests/optional.test
--- jq-1.6/tests/optional.test.iteration 2022-10-21 14:22:04.191734821 +0200
+++ jq-1.6/tests/optional.test 2022-10-21 14:23:45.820901911 +0200
@@ -17,4 +17,9 @@ strftime("%A, %B %e, %Y")
1435677542.822351
"Tuesday, June 30, 2015"
-
+# iteration must continue after hello
+.[]|tonumber?
+["1", "hello", "3", 4]
+1
+3
+4

851
SOURCES/0002-add-mantest.patch

@ -0,0 +1,851 @@
man.test from commit 50a7022ea68fb37faefdcd7a35661df72fbfd655

diff --git a/tests/man.test b/tests/man.test
new file mode 100644
index 0000000..2a49eff
--- /dev/null
+++ b/tests/man.test
@@ -0,0 +1,843 @@
+.
+"Hello, world!"
+"Hello, world!"
+
+.foo
+{"foo": 42, "bar": "less interesting data"}
+42
+
+.foo
+{"notfoo": true, "alsonotfoo": false}
+null
+
+.["foo"]
+{"foo": 42}
+42
+
+.foo?
+{"foo": 42, "bar": "less interesting data"}
+42
+
+.foo?
+{"notfoo": true, "alsonotfoo": false}
+null
+
+.["foo"]?
+{"foo": 42}
+42
+
+[.foo?]
+[1,2]
+[]
+
+.[0]
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
+{"name":"JSON", "good":true}
+
+.[2]
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
+null
+
+.[-2]
+[1,2,3]
+2
+
+.[2:4]
+["a","b","c","d","e"]
+["c", "d"]
+
+.[2:4]
+"abcdefghi"
+"cd"
+
+.[:3]
+["a","b","c","d","e"]
+["a", "b", "c"]
+
+.[-2:]
+["a","b","c","d","e"]
+["d", "e"]
+
+.[]
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
+{"name":"JSON", "good":true}
+{"name":"XML", "good":false}
+
+.[]
+[]
+
+.[]
+{"a": 1, "b": 1}
+1
+1
+
+.foo, .bar
+{"foo": 42, "bar": "something else", "baz": true}
+42
+"something else"
+
+.user, .projects[]
+{"user":"stedolan", "projects": ["jq", "wikiflow"]}
+"stedolan"
+"jq"
+"wikiflow"
+
+.[4,2]
+["a","b","c","d","e"]
+"e"
+"c"
+
+.[] | .name
+[{"name":"JSON", "good":true}, {"name":"XML", "good":false}]
+"JSON"
+"XML"
+
+(. + 2) * 5
+1
+15
+
+[.user, .projects[]]
+{"user":"stedolan", "projects": ["jq", "wikiflow"]}
+["stedolan", "jq", "wikiflow"]
+
+[ .[] | . * 2]
+[1, 2, 3]
+[2, 4, 6]
+
+{user, title: .titles[]}
+{"user":"stedolan","titles":["JQ Primer", "More JQ"]}
+{"user":"stedolan", "title": "JQ Primer"}
+{"user":"stedolan", "title": "More JQ"}
+
+{(.user): .titles}
+{"user":"stedolan","titles":["JQ Primer", "More JQ"]}
+{"stedolan": ["JQ Primer", "More JQ"]}
+
+..|.a?
+[[{"a":1}]]
+1
+
+.a + 1
+{"a": 7}
+8
+
+.a + .b
+{"a": [1,2], "b": [3,4]}
+[1,2,3,4]
+
+.a + null
+{"a": 1}
+1
+
+.a + 1
+{}
+1
+
+{a: 1} + {b: 2} + {c: 3} + {a: 42}
+null
+{"a": 42, "b": 2, "c": 3}
+
+4 - .a
+{"a":3}
+1
+
+. - ["xml", "yaml"]
+["xml", "yaml", "json"]
+["json"]
+
+10 / . * 3
+5
+6
+
+. / ", "
+"a, b,c,d, e"
+["a","b,c,d","e"]
+
+{"k": {"a": 1, "b": 2}} * {"k": {"a": 0,"c": 3}}
+null
+{"k": {"a": 0, "b": 2, "c": 3}}
+
+.[] | (1 / .)?
+[1,0,-1]
+1
+-1
+
+.[] | length
+[[1,2], "string", {"a":2}, null]
+2
+6
+1
+0
+
+utf8bytelength
+"\u03bc"
+2
+
+keys
+{"abc": 1, "abcd": 2, "Foo": 3}
+["Foo", "abc", "abcd"]
+
+keys
+[42,3,35]
+[0,1,2]
+
+map(has("foo"))
+[{"foo": 42}, {}]
+[true, false]
+
+map(has(2))
+[[0,1], ["a","b","c"]]
+[false, true]
+
+.[] | in({"foo": 42})
+["foo", "bar"]
+true
+false
+
+map(in([0,1]))
+[2, 0]
+[false, true]
+
+map(.+1)
+[1,2,3]
+[2,3,4]
+
+map_values(.+1)
+{"a": 1, "b": 2, "c": 3}
+{"a": 2, "b": 3, "c": 4}
+
+path(.a[0].b)
+null
+["a",0,"b"]
+
+[path(..)]
+{"a":[{"b":1}]}
+[[],["a"],["a",0],["a",0,"b"]]
+
+del(.foo)
+{"foo": 42, "bar": 9001, "baz": 42}
+{"bar": 9001, "baz": 42}
+
+del(.[1, 2])
+["foo", "bar", "baz"]
+["foo"]
+
+getpath(["a","b"])
+null
+null
+
+[getpath(["a","b"], ["a","c"])]
+{"a":{"b":0, "c":1}}
+[0, 1]
+
+setpath(["a","b"]; 1)
+null
+{"a": {"b": 1}}
+
+setpath(["a","b"]; 1)
+{"a":{"b":0}}
+{"a": {"b": 1}}
+
+setpath([0,"a"]; 1)
+null
+[{"a":1}]
+
+delpaths([["a","b"]])
+{"a":{"b":1},"x":{"y":2}}
+{"a":{},"x":{"y":2}}
+
+to_entries
+{"a": 1, "b": 2}
+[{"key":"a", "value":1}, {"key":"b", "value":2}]
+
+from_entries
+[{"key":"a", "value":1}, {"key":"b", "value":2}]
+{"a": 1, "b": 2}
+
+with_entries(.key |= "KEY_" + .)
+{"a": 1, "b": 2}
+{"KEY_a": 1, "KEY_b": 2}
+
+map(select(. >= 2))
+[1,5,3,0,7]
+[5,3,7]
+
+.[] | select(.id == "second")
+[{"id": "first", "val": 1}, {"id": "second", "val": 2}]
+{"id": "second", "val": 2}
+
+.[]|numbers
+[[],{},1,"foo",null,true,false]
+1
+
+1, empty, 2
+null
+1
+2
+
+[1,2,empty,3]
+null
+[1,2,3]
+
+try error("\($__loc__)") catch .
+null
+"{\"file\":\"<top-level>\",\"line\":1}"
+
+[paths]
+[1,[[],{"a":2}]]
+[[0],[1],[1,0],[1,1],[1,1,"a"]]
+
+[paths(scalars)]
+[1,[[],{"a":2}]]
+[[0],[1,1,"a"]]
+
+add
+["a","b","c"]
+"abc"
+
+add
+[1, 2, 3]
+6
+
+add
+[]
+null
+
+any
+[true, false]
+true
+
+any
+[false, false]
+false
+
+any
+[]
+false
+
+all
+[true, false]
+false
+
+all
+[true, true]
+true
+
+all
+[]
+true
+
+flatten
+[1, [2], [[3]]]
+[1, 2, 3]
+
+flatten(1)
+[1, [2], [[3]]]
+[1, 2, [3]]
+
+flatten
+[[]]
+[]
+
+flatten
+[{"foo": "bar"}, [{"foo": "baz"}]]
+[{"foo": "bar"}, {"foo": "baz"}]
+
+range(2;4)
+null
+2
+3
+
+[range(2;4)]
+null
+[2,3]
+
+[range(4)]
+null
+[0,1,2,3]
+
+[range(0;10;3)]
+null
+[0,3,6,9]
+
+[range(0;10;-1)]
+null
+[]
+
+[range(0;-5;-1)]
+null
+[0,-1,-2,-3,-4]
+
+floor
+3.14159
+3
+
+sqrt
+9
+3
+
+.[] | tonumber
+[1, "1"]
+1
+1
+
+.[] | tostring
+[1, "1", [1]]
+"1"
+"1"
+"[1]"
+
+map(type)
+[0, false, [], {}, null, "hello"]
+["number", "boolean", "array", "object", "null", "string"]
+
+.[] | (infinite * .) < 0
+[-1, 1]
+true
+false
+
+infinite, nan | type
+null
+"number"
+"number"
+
+sort
+[8,3,null,6]
+[null,3,6,8]
+
+sort_by(.foo)
+[{"foo":4, "bar":10}, {"foo":3, "bar":100}, {"foo":2, "bar":1}]
+[{"foo":2, "bar":1}, {"foo":3, "bar":100}, {"foo":4, "bar":10}]
+
+group_by(.foo)
+[{"foo":1, "bar":10}, {"foo":3, "bar":100}, {"foo":1, "bar":1}]
+[[{"foo":1, "bar":10}, {"foo":1, "bar":1}], [{"foo":3, "bar":100}]]
+
+min
+[5,4,2,7]
+2
+
+max_by(.foo)
+[{"foo":1, "bar":14}, {"foo":2, "bar":3}]
+{"foo":2, "bar":3}
+
+unique
+[1,2,5,3,5,3,1,3]
+[1,2,3,5]
+
+unique_by(.foo)
+[{"foo": 1, "bar": 2}, {"foo": 1, "bar": 3}, {"foo": 4, "bar": 5}]
+[{"foo": 1, "bar": 2}, {"foo": 4, "bar": 5}]
+
+unique_by(length)
+["chunky", "bacon", "kitten", "cicada", "asparagus"]
+["bacon", "chunky", "asparagus"]
+
+reverse
+[1,2,3,4]
+[4,3,2,1]
+
+contains("bar")
+"foobar"
+true
+
+contains(["baz", "bar"])
+["foobar", "foobaz", "blarp"]
+true
+
+contains(["bazzzzz", "bar"])
+["foobar", "foobaz", "blarp"]
+false
+
+contains({foo: 12, bar: [{barp: 12}]})
+{"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]}
+true
+
+contains({foo: 12, bar: [{barp: 15}]})
+{"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]}
+false
+
+indices(", ")
+"a,b, cd, efg, hijk"
+[3,7,12]
+
+indices(1)
+[0,1,2,1,3,1,4]
+[1,3,5]
+
+indices([1,2])
+[0,1,2,3,1,4,2,5,1,2,6,7]
+[1,8]
+
+index(", ")
+"a,b, cd, efg, hijk"
+3
+
+rindex(", ")
+"a,b, cd, efg, hijk"
+12
+
+inside("foobar")
+"bar"
+true
+
+inside(["foobar", "foobaz", "blarp"])
+["baz", "bar"]
+true
+
+inside(["foobar", "foobaz", "blarp"])
+["bazzzzz", "bar"]
+false
+
+inside({"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]})
+{"foo": 12, "bar": [{"barp": 12}]}
+true
+
+inside({"foo": 12, "bar":[1,2,{"barp":12, "blip":13}]})
+{"foo": 12, "bar": [{"barp": 15}]}
+false
+
+[.[]|startswith("foo")]
+["fo", "foo", "barfoo", "foobar", "barfoob"]
+[false, true, false, true, false]
+
+[.[]|endswith("foo")]
+["foobar", "barfoo"]
+[false, true]
+
+combinations
+[[1,2], [3, 4]]
+[1, 3]
+[1, 4]
+[2, 3]
+[2, 4]
+
+combinations(2)
+[0, 1]
+[0, 0]
+[0, 1]
+[1, 0]
+[1, 1]
+
+[.[]|ltrimstr("foo")]
+["fo", "foo", "barfoo", "foobar", "afoo"]
+["fo","","barfoo","bar","afoo"]
+
+[.[]|rtrimstr("foo")]
+["fo", "foo", "barfoo", "foobar", "foob"]
+["fo","","bar","foobar","foob"]
+
+explode
+"foobar"
+[102,111,111,98,97,114]
+
+implode
+[65, 66, 67]
+"ABC"
+
+split(", ")
+"a, b,c,d, e, "
+["a","b,c,d","e",""]
+
+join(", ")
+["a","b,c,d","e"]
+"a, b,c,d, e"
+
+join(" ")
+["a",1,2.3,true,null,false]
+"a 1 2.3 true false"
+
+[while(.<100; .*2)]
+1
+[1,2,4,8,16,32,64]
+
+[.,1]|until(.[0] < 1; [.[0] - 1, .[1] * .[0]])|.[1]
+4
+24
+
+recurse(.foo[])
+{"foo":[{"foo": []}, {"foo":[{"foo":[]}]}]}
+{"foo":[{"foo":[]},{"foo":[{"foo":[]}]}]}
+{"foo":[]}
+{"foo":[{"foo":[]}]}
+{"foo":[]}
+
+recurse
+{"a":0,"b":[1]}
+{"a":0,"b":[1]}
+0
+[1]
+1
+
+recurse(. * .; . < 20)
+2
+2
+4
+16
+
+walk(if type == "array" then sort else . end)
+[[4, 1, 7], [8, 5, 2], [3, 6, 9]]
+[[1,4,7],[2,5,8],[3,6,9]]
+
+walk( if type == "object" then with_entries( .key |= sub( "^_+"; "") ) else . end )
+[ { "_a": { "__b": 2 } } ]
+[{"a":{"b":2}}]
+
+$ENV.PAGER
+null
+"less"
+
+env.PAGER
+null
+"less"
+
+transpose
+[[1], [2,3]]
+[[1,2],[null,3]]
+
+bsearch(0)
+[0,1]
+0
+
+bsearch(0)
+[1,2,3]
+-1
+
+bsearch(4) as $ix | if $ix < 0 then .[-(1+$ix)] = 4 else . end
+[1,2,3]
+[1,2,3,4]
+
+"The input was \(.), which is one less than \(.+1)"
+42
+"The input was 42, which is one less than 43"
+
+[.[]|tostring]
+[1, "foo", ["foo"]]
+["1","foo","[\"foo\"]"]
+
+[.[]|tojson]
+[1, "foo", ["foo"]]
+["1","\"foo\"","[\"foo\"]"]
+
+[.[]|tojson|fromjson]
+[1, "foo", ["foo"]]
+[1,"foo",["foo"]]
+
+@html
+"This works if x < y"
+"This works if x &lt; y"
+
+@sh "echo \(.)"
+"O'Hara's Ale"
+"echo 'O'\\''Hara'\\''s Ale'"
+
+@base64
+"This is a message"
+"VGhpcyBpcyBhIG1lc3NhZ2U="
+
+@base64d
+"VGhpcyBpcyBhIG1lc3NhZ2U="
+"This is a message"
+
+fromdate
+"2015-03-05T23:51:47Z"
+1425599507
+
+strptime("%Y-%m-%dT%H:%M:%SZ")
+"2015-03-05T23:51:47Z"
+[2015,2,5,23,51,47,4,63]
+
+strptime("%Y-%m-%dT%H:%M:%SZ")|mktime
+"2015-03-05T23:51:47Z"
+1425599507
+
+.[] == 1
+[1, 1.0, "1", "banana"]
+true
+true
+false
+false
+
+if . == 0 then "zero" elif . == 1 then "one" else "many" end
+2
+"many"
+
+. < 5
+2
+true
+
+42 and "a string"
+null
+true
+
+(true, false) or false
+null
+true
+false
+
+(true, true) and (true, false)
+null
+true
+false
+true
+false
+
+[true, false | not]
+null
+[false, true]
+
+.foo // 42
+{"foo": 19}
+19
+
+.foo // 42
+{}
+42
+
+try .a catch ". is not an object"
+true
+". is not an object"
+
+[.[]|try .a]
+[{}, true, {"a":1}]
+[null, 1]
+
+try error("some exception") catch .
+true
+"some exception"
+
+[.[]|(.a)?]
+[{}, true, {"a":1}]
+[null, 1]
+
+test("foo")
+"foo"
+true
+
+.[] | test("a b c # spaces are ignored"; "ix")
+["xabcd", "ABC"]
+true
+true
+
+match("(abc)+"; "g")
+"abc abc"
+{"offset": 0, "length": 3, "string": "abc", "captures": [{"offset": 0, "length": 3, "string": "abc", "name": null}]}
+{"offset": 4, "length": 3, "string": "abc", "captures": [{"offset": 4, "length": 3, "string": "abc", "name": null}]}
+
+match("foo")
+"foo bar foo"
+{"offset": 0, "length": 3, "string": "foo", "captures": []}
+
+match(["foo", "ig"])
+"foo bar FOO"
+{"offset": 0, "length": 3, "string": "foo", "captures": []}
+{"offset": 8, "length": 3, "string": "FOO", "captures": []}
+
+match("foo (?<bar123>bar)? foo"; "ig")
+"foo bar foo foo foo"
+{"offset": 0, "length": 11, "string": "foo bar foo", "captures": [{"offset": 4, "length": 3, "string": "bar", "name": "bar123"}]}
+{"offset": 12, "length": 8, "string": "foo foo", "captures": [{"offset": -1, "length": 0, "string": null, "name": "bar123"}]}
+
+[ match("."; "g")] | length
+"abc"
+3
+
+capture("(?<a>[a-z]+)-(?<n>[0-9]+)")
+"xyzzy-14"
+{ "a": "xyzzy", "n": "14" }
+
+.bar as $x | .foo | . + $x
+{"foo":10, "bar":200}
+210
+
+. as $i|[(.*2|. as $i| $i), $i]
+5
+[10,5]
+
+. as [$a, $b, {c: $c}] | $a + $b + $c
+[2, 3, {"c": 4, "d": 5}]
+9
+
+.[] as [$a, $b] | {a: $a, b: $b}
+[[0], [0, 1], [2, 1, 0]]
+{"a":0,"b":null}
+{"a":0,"b":1}
+{"a":2,"b":1}
+
+.[] as {$a, $b, c: {$d, $e}} ?// {$a, $b, c: [{$d, $e}]} | {$a, $b, $d, $e}
+[{"a": 1, "b": 2, "c": {"d": 3, "e": 4}}, {"a": 1, "b": 2, "c": [{"d": 3, "e": 4}]}]
+{"a":1,"b":2,"d":3,"e":4}
+{"a":1,"b":2,"d":3,"e":4}
+
+.[] as {$a, $b, c: {$d}} ?// {$a, $b, c: [{$e}]} | {$a, $b, $d, $e}
+[{"a": 1, "b": 2, "c": {"d": 3, "e": 4}}, {"a": 1, "b": 2, "c": [{"d": 3, "e": 4}]}]
+{"a":1,"b":2,"d":3,"e":null}
+{"a":1,"b":2,"d":null,"e":4}
+
+.[] as [$a] ?// [$b] | if $a != null then error("err: \($a)") else {$a,$b} end
+[[3]]
+{"a":null,"b":3}
+
+def addvalue(f): . + [f]; map(addvalue(.[0]))
+[[1,2],[10,20]]
+[[1,2,1], [10,20,10]]
+
+def addvalue(f): f as $x | map(. + $x); addvalue(.[0])
+[[1,2],[10,20]]
+[[1,2,1,2], [10,20,1,2]]
+
+reduce .[] as $item (0; . + $item)
+[10,2,5,3]
+20
+
+isempty(empty)
+null
+true
+
+[limit(3;.[])]
+[0,1,2,3,4,5,6,7,8,9]
+[0,1,2]
+
+[first(range(.)), last(range(.)), nth(./2; range(.))]
+10
+[0,9,5]
+
+[range(.)]|[first, last, nth(5)]
+10
+[0,9,5]
+
+[foreach .[] as $item ([[],[]]; if $item == null then [[],.[0]] else [(.[0] + [$item]),[]] end; if $item == null then .[1] else empty end)]
+[1,2,3,4,null,"a","b",null]
+[[1,2,3,4],["a","b"]]
+
+def range(init; upto; by): def _range: if (by > 0 and . < upto) or (by < 0 and . > upto) then ., ((.+by)|_range) else . end; if by == 0 then init else init|_range end | select((by > 0 and . < upto) or (by < 0 and . > upto)); range(0; 10; 3)
+null
+0
+3
+6
+9
+
+def while(cond; update): def _while: if cond then ., (update | _while) else empty end; _while; [while(.<100; .*2)]
+1
+[1,2,4,8,16,32,64]
+
+[1|truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]])]
+1
+[[[0],2],[[0]]]
+
+fromstream(1|truncate_stream([[0],1],[[1,0],2],[[1,0]],[[1]]))
+null
+[2]
+
+. as $dot|fromstream($dot|tostream)|.==$dot
+[0,[1,{"a":1},{"b":2}]]
+true
+
+(..|select(type=="boolean")) |= if . then 1 else 0 end
+[true,false,[5,true,[true,[false]],false]]
+[1,0,[5,1,[1,[0]],0]]
+
+.foo += 1
+{"foo": 42}
+{"foo": 43}
+

244
SOURCES/0003-fix-pthread-segfault.patch

@ -0,0 +1,244 @@
commit fead9669cb67badb22789d3ed1888779ed85c679
Author: Tomas Halman <thalman@redhat.com>
Date: Thu Mar 9 11:34:44 2023 +0100

Test that jq works in threads
This patch implements test that searches a key in simple
json in pthread.

diff -up jq-1.6/src/jq_test.c.orig jq-1.6/src/jq_test.c
--- jq-1.6/src/jq_test.c.orig 2023-03-09 14:02:16.980062057 +0100
+++ jq-1.6/src/jq_test.c 2023-03-09 14:03:38.347017032 +0100
@@ -2,12 +2,17 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+#endif
#include "jv.h"
#include "jq.h"
static void jv_test();
static void run_jq_tests(jv, int, FILE *, int, int);
-
+#ifdef HAVE_PTHREAD
+static void run_jq_pthread_tests();
+#endif
int jq_testsuite(jv libdirs, int verbose, int argc, char* argv[]) {
FILE *testdata = stdin;
@@ -32,6 +37,9 @@ int jq_testsuite(jv libdirs, int verbose
}
}
run_jq_tests(libdirs, verbose, testdata, skip, take);
+#ifdef HAVE_PTHREAD
+ run_jq_pthread_tests();
+#endif
return 0;
}
@@ -105,7 +113,7 @@ static void run_jq_tests(jv lib_dirs, in
if (buf[0] == '\n' || (buf[0] == '\r' && buf[1] == '\n'))
break;
}
-
+
must_fail = 0;
check_msg = 0;
@@ -229,7 +237,7 @@ static void run_jq_tests(jv lib_dirs, in
total_skipped = tests_to_skip - skip;
}
- printf("%d of %d tests passed (%d malformed, %d skipped)\n",
+ printf("%d of %d tests passed (%d malformed, %d skipped)\n",
passed, tests, invalid, total_skipped);
if (skip > 0) {
@@ -241,6 +249,88 @@ static void run_jq_tests(jv lib_dirs, in
}
+/// pthread regression test
+#ifdef HAVE_PTHREAD
+#define NUMBER_OF_THREADS 3
+struct test_pthread_data {
+ int result;
+};
+
+static int test_pthread_jq_parse(jq_state *jq, struct jv_parser *parser)
+{
+ int rv = 0;
+ jv value;
+
+ value = jv_parser_next(parser);
+ while (jv_is_valid(value)) {
+ jq_start(jq, value, 0);
+ jv result = jq_next(jq);
+
+ while (jv_is_valid(result)) {
+ jv_free(result);
+ result = jq_next(jq);
+ }
+ jv_free(result);
+ value = jv_parser_next(parser);
+ }
+ jv_free(value);
+ return rv;
+}
+
+static void *test_pthread_run(void *ptr) {
+ int rv;
+ jq_state *jq;
+ const char *prg = ".data";
+ const char *buf = "{ \"data\": 1 }";
+ struct test_pthread_data *data = ptr;
+
+ jq = jq_init();
+ if (jq_compile(jq, prg) == 0) {
+ jq_teardown(&jq);
+ return NULL;
+ }
+
+ struct jv_parser *parser = jv_parser_new(0);
+ jv_parser_set_buf(parser, buf, strlen(buf), 0);
+ rv = test_pthread_jq_parse(jq, parser);
+
+ data->result = rv;
+
+ jv_parser_free(parser);
+ jq_teardown(&jq);
+ return NULL;
+}
+
+static void run_jq_pthread_tests() {
+ pthread_t threads[NUMBER_OF_THREADS];
+ struct test_pthread_data data[NUMBER_OF_THREADS];
+ int createerror;
+ int a;
+
+ memset(&threads, 0, sizeof(threads));
+ memset(&data, 0, sizeof(data));
+
+ // Create all threads
+ for (a = 0; a < NUMBER_OF_THREADS; ++a) {
+ createerror = pthread_create(&threads[a], NULL, test_pthread_run, &data[a]);
+ assert(createerror == 0);
+ }
+
+ // wait for all threads
+ for(a = 0; a < NUMBER_OF_THREADS; ++a) {
+ if (threads[a] != 0) {
+ pthread_join(threads[a], NULL);
+ }
+ }
+
+ // check results
+ for(a = 0; a < NUMBER_OF_THREADS; ++a) {
+ assert(data[a].result == 0);
+ }
+}
+#endif // HAVE_PTHREAD
+
+
static void jv_test() {
/// JSON parser regression tests
{

commit f05c5bb521f404592b137e02a1b8abd50da87ca3
Author: Tomas Halman <thalman@redhat.com>
Date: Wed Mar 1 20:07:28 2023 +0100

Fix segmentation fault when using jq in threads
In previous code nomem_handler in jv_alloc.c is called only once
and therefore the structure is not initialized for second and
following threads.
This leads to segmentation fault in multi-threading environment.
This patch moves initialization of nomem_handler out of the
pthread_once call.

diff -up jq-1.6/src/jv_alloc.c.orig jq-1.6/src/jv_alloc.c
--- jq-1.6/src/jv_alloc.c.orig 2018-11-02 02:49:29.000000000 +0100
+++ jq-1.6/src/jv_alloc.c 2023-03-09 14:13:47.810177037 +0100
@@ -45,9 +45,11 @@ static void memory_exhausted() {
#ifdef HAVE_PTHREAD_KEY_CREATE
#include <pthread.h>
-pthread_key_t nomem_handler_key;
-pthread_once_t mem_once = PTHREAD_ONCE_INIT;
+static pthread_key_t nomem_handler_key;
+static pthread_once_t mem_once = PTHREAD_ONCE_INIT;
+/* tsd_fini is called on application exit */
+/* it clears the nomem_handler allocated in the main thread */
static void tsd_fini(void) {
struct nomem_handler *nomem_handler;
nomem_handler = pthread_getspecific(nomem_handler_key);
@@ -57,30 +59,45 @@ static void tsd_fini(void) {
}
}
+/* The tsd_fini_thread is a destructor set by calling */
+/* pthread_key_create(&nomem_handler_key, tsd_fini_thread) */
+/* It is called when thread ends */
+static void tsd_fini_thread(void *nomem_handler) {
+ free(nomem_handler);
+}
+
static void tsd_init(void) {
- if (pthread_key_create(&nomem_handler_key, NULL) != 0) {
- fprintf(stderr, "error: cannot create thread specific key");
+ if (pthread_key_create(&nomem_handler_key, tsd_fini_thread) != 0) {
+ fprintf(stderr, "jq: error: cannot create thread specific key");
abort();
}
if (atexit(tsd_fini) != 0) {
- fprintf(stderr, "error: cannot set an exit handler");
+ fprintf(stderr, "jq: error: cannot set an exit handler");
abort();
}
- struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));
- if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
- fprintf(stderr, "error: cannot set thread specific data");
- abort();
+}
+
+static void tsd_init_nomem_handler(void)
+{
+ if (pthread_getspecific(nomem_handler_key) == NULL) {
+ struct nomem_handler *nomem_handler = calloc(1, sizeof(struct nomem_handler));
+ if (pthread_setspecific(nomem_handler_key, nomem_handler) != 0) {
+ fprintf(stderr, "jq: error: cannot set thread specific data");
+ abort();
+ }
}
}
void jv_nomem_handler(jv_nomem_handler_f handler, void *data) {
pthread_once(&mem_once, tsd_init); // cannot fail
+ tsd_init_nomem_handler();
+
struct nomem_handler *nomem_handler;
nomem_handler = pthread_getspecific(nomem_handler_key);
if (nomem_handler == NULL) {
handler(data);
- fprintf(stderr, "error: cannot allocate memory\n");
+ fprintf(stderr, "jq: error: cannot allocate memory\n");
abort();
}
nomem_handler->handler = handler;
@@ -91,6 +108,8 @@ static void memory_exhausted() {
struct nomem_handler *nomem_handler;
pthread_once(&mem_once, tsd_init);
+ tsd_init_nomem_handler();
+
nomem_handler = pthread_getspecific(nomem_handler_key);
if (nomem_handler)
nomem_handler->handler(nomem_handler->data); // Maybe handler() will longjmp() to safety

4562
SOURCES/0004-make-jq-fast.patch

File diff suppressed because it is too large Load Diff

27596
SOURCES/jq-decimal-literal-number.patch

File diff suppressed because it is too large Load Diff

124
SPECS/jq.spec

@ -1,29 +1,23 @@
## START: Set by rpmautospec
## (rpmautospec version 0.3.5)
## RPMAUTOSPEC: autorelease, autochangelog
%define autorelease(e:s:pb:n) %{?-p:0.}%{lua:
release_number = 1;
base_release_number = tonumber(rpm.expand("%{?-b*}%{!?-b:1}"));
print(release_number + base_release_number - 1);
}%{?-e:.%{-e*}}%{?-s:.%{-s*}}%{!?-n:%{?dist}}
## END: Set by rpmautospec

%bcond_without check

Name: jq Name: jq
Version: 1.7.1 Version: 1.6
Release: %autorelease Release: 16%{?dist}
Summary: Command-line JSON processor Summary: Command-line JSON processor


License: MIT and ASL 2.0 and CC-BY and GPLv3 License: MIT and ASL 2.0 and CC-BY and GPLv3
URL: https://jqlang.github.io/jq/ URL: http://stedolan.github.io/jq/
Source0: https://github.com/jqlang/jq/releases/download/%{name}-%{version}/%{name}-%{version}.tar.gz Source0: https://github.com/stedolan/jq/releases/download/%{name}-%{version}/%{name}-%{version}.tar.gz
# Backport of PR#1752 for RHBZ#2008979
Patch0: jq-decimal-literal-number.patch
Patch1: 0001-iterration-problem-for-non-decimal-string.patch
Patch2: 0002-add-mantest.patch
Patch3: 0003-fix-pthread-segfault.patch
Patch4: 0004-make-jq-fast.patch


BuildRequires: gcc BuildRequires: gcc
BuildRequires: flex BuildRequires: flex
BuildRequires: bison BuildRequires: bison
BuildRequires: chrpath
BuildRequires: oniguruma-devel BuildRequires: oniguruma-devel
BuildRequires: chrpath


%ifarch %{valgrind_arches} %ifarch %{valgrind_arches}
BuildRequires: valgrind BuildRequires: valgrind
@ -37,18 +31,18 @@ BuildRequires: libtool
%description %description
lightweight and flexible command-line JSON processor lightweight and flexible command-line JSON processor


jq is like sed for JSON data – you can use it to slice jq is like sed for JSON data – you can use it to slice
and filter and map and transform structured data with and filter and map and transform structured data with
the same ease that sed, awk, grep and friends let you the same ease that sed, awk, grep and friends let you
play with text. play with text.


It is written in portable C, and it has zero runtime It is written in portable C, and it has zero runtime
dependencies. dependencies.


jq can mangle the data format that you have into the jq can mangle the data format that you have into the
one that you want with very little effort, and the one that you want with very little effort, and the
program to do so is often shorter and simpler than program to do so is often shorter and simpler than
you'd expect. you'd expect.


%package devel %package devel
Summary: Development files for %{name} Summary: Development files for %{name}
@ -59,12 +53,12 @@ Development files for %{name}




%prep %prep
%autosetup -n %{name}-%{name}-%{version} -p1 %autosetup -n %{name}-%{version} -p1


%build %build
autoreconf -if autoreconf -if
%configure --disable-static %configure --disable-static
%make_build make %{?_smp_mflags}
# Docs already shipped in jq's tarball. # Docs already shipped in jq's tarball.
# In order to build the manual page, it # In order to build the manual page, it
# is necessary to install rake, rubygem-ronn # is necessary to install rake, rubygem-ronn
@ -80,71 +74,64 @@ autoreconf -if
# $ make real_docs # $ make real_docs


%install %install
%make_install make DESTDIR=%{buildroot} install
find %{buildroot} -name '*.la' -exec rm -f {} ';' find %{buildroot} -name '*.la' -exec rm -f {} ';'
chrpath --delete %{buildroot}/usr/bin/jq


# Delete build-time RPATH that is unnecessary on an installed
# system - rhbz#1987608
chrpath -d %{buildroot}%{_bindir}/%{name}

%if %{with check}
%check %check
# Valgrind used, so restrict architectures for check # Valgrind used, so restrict architectures for check
%ifarch %{ix86} x86_64 %ifarch %{ix86} x86_64
make check make check
%endif %endif
%endif
%ldconfig_scriptlets


%files %files
%license COPYING
%doc AUTHORS COPYING NEWS.md README.md
%{_bindir}/%{name} %{_bindir}/%{name}
%{_libdir}/libjq.so.* %{_libdir}/libjq.so.*
%{_datadir}/man/man1/jq.1.gz %{_datadir}/man/man1/jq.1.gz
%{_datadir}/doc/jq/AUTHORS
%{_datadir}/doc/jq/COPYING
%{_datadir}/doc/jq/README
%{_datadir}/doc/jq/README.md


%files devel %files devel
%{_includedir}/jq.h %{_includedir}/jq.h
%{_includedir}/jv.h %{_includedir}/jv.h
%{_libdir}/libjq.so %{_libdir}/libjq.so
%{_libdir}/pkgconfig/libjq.pc


%changelog
* Fri Jan 05 2024 jonathanspw <jonathan@almalinux.org> - 1.7.1-1
- update to 1.7.1 rhbz#2252340

* Fri Sep 08 2023 Mikel Olasagasti Uranga <mikel@olasagasti.info> - 1.7-1
- Update to 1.7

* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-17
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild


* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-16 %changelog
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild * Fri Oct 13 2023 Tomas Halman <thalman@redhat.com> - 1.6-16

- Make jq 1.6 fast
* Fri Jan 13 2023 Florian Weimer <fweimer@redhat.com> - 1.6-15 - Resolves: RHEL-13431
- Port configure script to C99


* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-14 * Thu Mar 9 2023 Tomas Halman <thalman@redhat.com> - 1.6-15
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - jq segfault when used in threads
- Resolves: rhbz#2176542


* Fri Mar 11 2022 Neal Gompa <ngompa@fedoraproject.org> - 1.6-13 * Fri Nov 4 2022 Tomas Halman <thalman@redhat.com> - 1.6-6
- Use make macros - Add mantest to the gating
- https://fedoraproject.org/wiki/Changes/UseMakeBuildInstallMacro - Related: rhbz#2049594


* Tue Mar 08 2022 Davide Cavalca <dcavalca@fedoraproject.org> - 1.6-12 * Fri Oct 21 2022 Tomas Halman <thalman@redhat.com> - 1.6-13
- Backport PR#2400 to fix iteration for non-decimal strings (rhbz#2017285) - jq try/catch stops iteration over items
Resolves: rhbz#2049594


* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-11 * Mon Nov 15 2021 Tomas Halman <thalman@redhat.com>
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - Strip rpath from jq binary
Related: rhbz#2008983


* Wed Sep 29 2021 Davide Cavalca <dcavalca@fedoraproject.org> - 1.6-10 * Wed Sep 29 2021 Davide Cavalca <dcavalca@centosproject.org> - 1.6-10
- Backport PR#1752 to fix an integer logic issue (rhbz#2008979) - Backport PR#1752 to fix an integer logic issue
Resolves: rhbz#2008983


* Thu Aug 12 2021 Lon Hohberger <lon@redhat.com> - 1.6-9 * Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 1.6-9
- Drop build-time RPATH from jq binary (rhbz#1987608) - Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688


* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-8 * Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 1.6-8
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937


* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-7 * Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 1.6-7
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
@ -220,4 +207,3 @@ make check


* Fri Oct 18 2013 Flavio Percoco <flavio@redhat.com> - 1.3-1 * Fri Oct 18 2013 Flavio Percoco <flavio@redhat.com> - 1.3-1
- Initial package release. - Initial package release.


Loading…
Cancel
Save