ndspi->ndspi_snapend = ndo->ndo_snapend;
ndspi->ndspi_prev = ndo->ndo_packet_info_stack;
- /* No new packet pointer, either */
- if (new_snapend < ndo->ndo_snapend)
- ndo->ndo_snapend = new_snapend;
+ /*
+ * Make sure the new snapend is sane.
+ *
+ * If it's after the current snapend, it's not valid. We
+ * silently ignore the new setting; that means that our callers
+ * don't have to do this check themselves, and also means that
+ * if the new length is used when dissecting, we'll go past the
+ * snapend and report an error.
+ *
+ * If it's before the beginning of the packet, it's not valid.
+ * That "should not happen", but might happen with a *very*
+ * large adjustment to the snapend; our callers *should* check
+ * for that, so we fail if they haven't done so.
+ */
+ if (new_snapend <= ndo->ndo_snapend) {
+ /* Snapend isn't past the previous snapend */
+ if (new_snapend >= ndo->ndo_packetp) {
+ /* And it isn't before the beginning of the packet */
+ ndo->ndo_snapend = new_snapend;
+ } else {
+ /* But it's before the beginning of the packet */
+ ND_PRINT(" [new snapend before beginning of packet in nd_push_snapend]");
+ nd_bug_longjmp(ndo);
+ }
+ }
ndo->ndo_packet_info_stack = ndspi;
return (1); /* success */
nd_change_snapend(netdissect_options *ndo, const u_char *new_snapend)
{
struct netdissect_saved_packet_info *ndspi;
+ const u_char *previous_snapend;
ndspi = ndo->ndo_packet_info_stack;
- if (ndspi->ndspi_prev != NULL) {
- if (new_snapend <= ndspi->ndspi_prev->ndspi_snapend)
- ndo->ndo_snapend = new_snapend;
- } else {
- if (new_snapend < ndo->ndo_snapend)
+ if (ndspi->ndspi_prev != NULL)
+ previous_snapend = ndspi->ndspi_prev->ndspi_snapend;
+ else
+ previous_snapend = ndo->ndo_snapend;
+ /*
+ * Make sure the new snapend is sane.
+ *
+ * If it's after the current snapend, it's not valid. We
+ * silently ignore the new setting; that means that our callers
+ * don't have to do this check themselves, and also means that
+ * if the new length is used when dissecting, we'll go past the
+ * snapend and report an error.
+ *
+ * If it's before the beginning of the packet, it's not valid.
+ * That "should not happen", but might happen with a *very*
+ * large adjustment to the snapend; our callers *should* check
+ * for that, so we fail if they haven't done so.
+ */
+ if (new_snapend <= previous_snapend) {
+ /* Snapend isn't past the previous snapend */
+ if (new_snapend >= ndo->ndo_packetp) {
+ /* And it isn't before the beginning of the packet */
ndo->ndo_snapend = new_snapend;
+ } else {
+ /* But it's before the beginning of the packet */
+ ND_PRINT(" [new snapend before beginning of packet in nd_push_snapend]");
+ nd_bug_longjmp(ndo);
+ }
}
}
};
/* 'val' value(s) for longjmp */
-#define ND_TRUNCATED 1
+#define ND_TRUNCATED 1 /* packet data too short */
+#define ND_BUG 2 /* bug of some sort */
struct netdissect_options {
int ndo_bflag; /* print 4 byte ASes in ASDOT notation */
#endif /* _AIX */
}
+static inline NORETURN void
+nd_bug_longjmp(netdissect_options *ndo)
+{
+ longjmp(ndo->ndo_early_end, ND_BUG);
+#ifdef _AIX
+ /*
+ * In AIX <setjmp.h> decorates longjmp() with "#pragma leaves", which tells
+ * XL C that the function is noreturn, but GCC remains unaware of that and
+ * yields a "'noreturn' function does return" warning.
+ */
+ ND_UNREACHABLE
+#endif /* _AIX */
+}
+
#define PT_VAT 1 /* Visual Audio Tool */
#define PT_WB 2 /* distributed White Board */
#define PT_RPC 3 /* Remote Procedure Call */