From 8cea9a2e28b94ac63b358fd087217b66824c61cd Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 24 Apr 2019 17:05:02 -0700 Subject: [PATCH] gcs/gcs: ensure match zero hash --- gcs/gcs.go | 96 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 37 deletions(-) diff --git a/gcs/gcs.go b/gcs/gcs.go index c544a42..ffdd012 100644 --- a/gcs/gcs.go +++ b/gcs/gcs.go @@ -304,12 +304,11 @@ func (f *Filter) Match(key [KeySize]byte, data []byte) (bool, error) { term = fastReduction(term, nphi, nplo) // Go through the search filter and look for the desired value. - var lastValue uint64 - for lastValue < term { - + var value uint64 + for i := uint32(0); i < f.N(); i++ { // Read the difference between previous and new value from // bitstream. - value, err := f.readFullUint64(b) + delta, err := f.readFullUint64(b) if err != nil { if err == io.EOF { return false, nil @@ -317,15 +316,25 @@ func (f *Filter) Match(key [KeySize]byte, data []byte) (bool, error) { return false, err } - // Add the previous value to it. - value += lastValue - if value == term { - return true, nil - } + // Add the delta to the previous value. + value += delta + switch { - lastValue = value + // The current value matches our query term, success. + case value == term: + return true, nil + + // The current value is greater than our query term, thus no + // future decoded value can match because the values + // monotonically increase. + case value > term: + return false, nil + } } + // All values were decoded and none produced a successful match. This + // indicates that the items in the filter were all smaller than our + // target. return false, nil } @@ -382,42 +391,55 @@ func (f *Filter) ZipMatchAny(key [KeySize]byte, data [][]byte) (bool, error) { } sort.Sort(values) + querySize := len(values) + // Zip down the filters, comparing values until we either run out of // values to compare in one of the filters or we reach a matching // value. - var lastValue1, lastValue2 uint64 - lastValue2 = values[0] - i := 1 - for lastValue1 != lastValue2 { - // Check which filter to advance to make sure we're comparing - // the right values. - switch { - case lastValue1 > lastValue2: - // Advance filter created from search terms or return - // false if we're at the end because nothing matched. - if i < len(values) { - lastValue2 = values[i] - i++ - } else { + var ( + value uint64 + queryIndex int + ) +out: + for i := uint32(0); i < f.N(); i++ { + // Advance filter we're searching or return false if we're at + // the end because nothing matched. + delta, err := f.readFullUint64(b) + if err != nil { + if err == io.EOF { return false, nil } - case lastValue2 > lastValue1: - // Advance filter we're searching or return false if - // we're at the end because nothing matched. - value, err := f.readFullUint64(b) - if err != nil { - if err == io.EOF { - return false, nil - } - return false, err + return false, err + } + value += delta + + for { + switch { + + // All query items have been exhausted and we haven't + // had a match, therefore there are no matches. + case queryIndex == querySize: + return false, nil + + // The current item in the query matches the decoded + // value, success. + case values[queryIndex] == value: + return true, nil + + // The current item in the query is greater than the + // current decoded value, continue to decode the next + // delta and try again. + case values[queryIndex] > value: + continue out } - lastValue1 += value + + queryIndex++ } } - // If we've made it this far, an element matched between filters so we - // return true. - return true, nil + // All items in the filter were decoded and none produced a successful + // match. + return false, nil } // HashMatchAny returns checks whether any []byte value is likely (within