BIND 10 trac1883, updated. d4ba721af6702333ee6f6130f0f0fe2efc3ff859 [1883] added one suggested test
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Jul 5 21:27:10 UTC 2012
The branch, trac1883 has been updated
via d4ba721af6702333ee6f6130f0f0fe2efc3ff859 (commit)
via abf5722f11570ebcd303d67d0877efab8015e9d8 (commit)
from 1e85f1ea840dcd93f80f154600d762b030888f8f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d4ba721af6702333ee6f6130f0f0fe2efc3ff859
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Thu Jul 5 14:27:00 2012 -0700
[1883] added one suggested test
commit abf5722f11570ebcd303d67d0877efab8015e9d8
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Thu Jul 5 14:22:09 2012 -0700
[1883] make sure the conversion to Py_hash_t by tp_hash is safe and avoids -1.
also constify some variables more.
-----------------------------------------------------------------------
Summary of changes:
src/lib/dns/python/name_python.cc | 5 ++-
src/lib/dns/python/pydnspp_common.h | 50 ++++++++++++++++++++++++
src/lib/dns/python/rrclass_python.cc | 4 +-
src/lib/dns/python/rrtype_python.cc | 4 +-
src/lib/dns/python/tests/rrtype_python_test.py | 1 +
5 files changed, 58 insertions(+), 6 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/lib/dns/python/name_python.cc b/src/lib/dns/python/name_python.cc
index c24d24d..277595a 100644
--- a/src/lib/dns/python/name_python.cc
+++ b/src/lib/dns/python/name_python.cc
@@ -522,8 +522,9 @@ Name_isWildCard(s_Name* self) {
Py_hash_t
Name_hash(PyObject* pyself) {
- s_Name* const self = static_cast<s_Name*>(pyself);
- return (LabelSequence(*self->cppobj).getHash(false));
+ const s_Name* const self = static_cast<s_Name*>(pyself);
+ return (convertToPyHash<size_t>(
+ LabelSequence(*self->cppobj).getHash(false)));
}
} // end of unnamed namespace
diff --git a/src/lib/dns/python/pydnspp_common.h b/src/lib/dns/python/pydnspp_common.h
index e9e9359..1513dd9 100644
--- a/src/lib/dns/python/pydnspp_common.h
+++ b/src/lib/dns/python/pydnspp_common.h
@@ -17,6 +17,9 @@
#include <Python.h>
+#include <boost/static_assert.hpp>
+
+#include <climits> // for CHAR_BIT
#include <stdexcept>
#include <string>
@@ -48,6 +51,53 @@ int addClassVariable(PyTypeObject& c, const char* name, PyObject* obj);
#if PY_MINOR_VERSION < 2
typedef long Py_hash_t;
#endif
+
+/// \brief Convert a hash value of arbitrary type to a Python hash value.
+///
+/// This templated function is a convenient wrapper to produce a valid hash
+/// value of type Py_hash_t, which is expected to be used as the return value
+/// of a PyTypeObject.tp_hash implementation. Py_hash_t is a signed integer
+/// the same size as Py_ssize_t.
+///
+/// The major concern is that -1 means an error in tp_hash and so we need to
+/// ensure that this value is never returned.
+///
+/// If the size of the original hash type is small enough, we convert
+/// the original hash value to a value of Py_hash_t, resetting all higher bits
+/// to 0. Due to the assumption on the sizes, the conversion to HashvalType
+/// is safe, and (after clearing the higher bits) results in a valid positive
+/// value.
+///
+/// If the size of the input and return types is the same, we clear the
+/// highest bit of the original hash so the resulting value will be in a valid
+/// positive range of Py_hash_t. If the original type is unsigned, there's
+/// probably no better conversion than this because otherwise the conversion
+/// to Py_hash_t could result in an undefined behavior. If the original type
+/// is signed, this conversion reduces the effective value range of the
+/// original hash. If this is not desired, the caller should convert it
+/// by itself (note that -1 should be still avoided).
+///
+/// This function does not support the case where the size of the original
+/// hash type is larger than that of Py_hash_t.
+template <typename HashvalType>
+Py_hash_t
+convertToPyHash(HashvalType val) {
+ BOOST_STATIC_ASSERT(sizeof(HashvalType) <= sizeof(Py_hash_t));
+
+ if (sizeof(HashvalType) < sizeof(Py_hash_t)) {
+ // The original hash type has small enough. Do trivial conversion.
+ const Py_hash_t mask = ~(static_cast<Py_hash_t>(-1) <<
+ (CHAR_BIT * sizeof(HashvalType)));
+ return (static_cast<Py_hash_t>(val) & mask);
+ } else {
+ // Clear the highest bit of the original hash so the conversion is
+ // safe and avoids -1.
+ const HashvalType mask = ~(static_cast<HashvalType>(1) <<
+ (CHAR_BIT * sizeof(HashvalType) - 1));
+ BOOST_STATIC_ASSERT(mask != static_cast<HashvalType>(-1));
+ return (val & mask);
+ }
+}
} // namespace python
} // namespace dns
} // namespace isc
diff --git a/src/lib/dns/python/rrclass_python.cc b/src/lib/dns/python/rrclass_python.cc
index b94dc02..a566f47 100644
--- a/src/lib/dns/python/rrclass_python.cc
+++ b/src/lib/dns/python/rrclass_python.cc
@@ -267,8 +267,8 @@ PyObject* RRClass_ANY(s_RRClass*) {
Py_hash_t
RRClass_hash(PyObject* pyself) {
- s_RRClass* const self = static_cast<s_RRClass*>(pyself);
- return (self->cppobj->getCode());
+ const s_RRClass* const self = static_cast<s_RRClass*>(pyself);
+ return (convertToPyHash<uint16_t>(self->cppobj->getCode()));
}
} // end anonymous namespace
diff --git a/src/lib/dns/python/rrtype_python.cc b/src/lib/dns/python/rrtype_python.cc
index bf22e8d..97b66d4 100644
--- a/src/lib/dns/python/rrtype_python.cc
+++ b/src/lib/dns/python/rrtype_python.cc
@@ -371,8 +371,8 @@ RRType_ANY(s_RRType*) {
Py_hash_t
RRType_hash(PyObject* pyself) {
- s_RRType* const self = static_cast<s_RRType*>(pyself);
- return (self->cppobj->getCode());
+ const s_RRType* const self = static_cast<s_RRType*>(pyself);
+ return (convertToPyHash<uint16_t>(self->cppobj->getCode()));
}
} // end anonymous namespace
diff --git a/src/lib/dns/python/tests/rrtype_python_test.py b/src/lib/dns/python/tests/rrtype_python_test.py
index fde9c74..4548b50 100644
--- a/src/lib/dns/python/tests/rrtype_python_test.py
+++ b/src/lib/dns/python/tests/rrtype_python_test.py
@@ -121,6 +121,7 @@ class TestModuleSpec(unittest.TestCase):
# value, we can predict the comparison result.
self.assertEqual(hash(RRType.AAAA()), hash(RRType("AAAA")))
self.assertEqual(hash(RRType("aaaa")), hash(RRType("AAAA")))
+ self.assertEqual(hash(RRType(28)), hash(RRType("AAAA")))
self.assertNotEqual(hash(RRType.A()), hash(RRType.NS()))
self.assertNotEqual(hash(RRType.AAAA()), hash(RRType("Type65535")))
More information about the bind10-changes
mailing list